PlaTyPuS8

Hi!

I have a FlowDocumentScrollViewer that is included in a ListBox.... My problem is that the listbox doesn't scroll when we have the cursor on the FlowDocumentScrollViewer .

How can I make the listbox scroll even if the mouse cursor is on the flowdocument (without using IsHitTestVisible="False" on the flowdocument... because I want to keep the controls in this one!)

I have uploaded a little project to let you try it : http://bastien.duotone.ch/ScrollProblem.zip

Thx for your help!!!

+++



Re: Windows Presentation Foundation (WPF) Make it scroll... (FlowDocumentScrollViewer)

PlaTyPuS8

up



Re: Windows Presentation Foundation (WPF) Make it scroll... (FlowDocumentScrollViewer)

Dr. WPF

The only way to make this work is to handle the preview events on the ListBox. Otherwise, once the key events have made it to the FlowDocumentScrollViewer, it will handle them and translate those events to its internal scroll commands.

I assume you're okay with the side effects of handling preview events. (If you have controls within the FlowDocument... perhaps a TextBox... that should respond to keyboard events like Left, Right, etc., these controls will not function properly if you handle the preview events on the ListBox.) If this is not an acceptable consequence, then you will have to look for a solution that does not involve a FlowDocumentScrollViewer.

Here is the preview solution...

First, add a PreviewKeyDown handler to the ListBox like this:

Code Block

<ListBox IsSynchronizedWithCurrentItem="True"

Margin="97,100,137,0"

VerticalAlignment="Top"

Height="99"

PreviewKeyDown="PreviewListBoxKeyDown"

ScrollViewer.CanContentScroll="False">

Then use the following code to process the preview key events and change them into scroll actions:

Code Block

public partial class Window1 : System.Windows.Window

{

public Window1()

{

InitializeComponent();

}

ScrollViewer _listboxScrollViewer = null;

void PreviewListBoxKeyDown(object sender, KeyEventArgs e)

{

// ignore keystroke if Alt is pressed

if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) != 0)

return;

// make sure we have a reference to the ListBox's ScrollViewer

if (_listboxScrollViewer == null)

{

_listboxScrollViewer = GetDescendantByType(

sender as Visual, typeof(ScrollViewer)) as ScrollViewer;

}

if (_listboxScrollViewer == null) return;

// handle the scroll keys

switch (e.Key)

{

case Key.Up:

_listboxScrollViewer.LineUp();

e.Handled = true;

break;

case Key.Down:

_listboxScrollViewer.LineDown();

e.Handled = true;

break;

case Key.Left:

if (FlowDirection == FlowDirection.RightToLeft)

_listboxScrollViewer.LineRight();

else

_listboxScrollViewer.LineLeft();

e.Handled = true;

break;

case Key.Right:

if (FlowDirection == FlowDirection.RightToLeft)

_listboxScrollViewer.LineLeft();

else

_listboxScrollViewer.LineRight();

e.Handled = true;

break;

case Key.PageUp:

_listboxScrollViewer.PageUp();

e.Handled = true;

break;

case Key.PageDown:

_listboxScrollViewer.PageDown();

e.Handled = true;

break;

case Key.Home:

if ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0)

_listboxScrollViewer.ScrollToTop();

else

_listboxScrollViewer.ScrollToLeftEnd();

e.Handled = true;

break;

case Key.End:

if ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0)

_listboxScrollViewer.ScrollToBottom();

else

_listboxScrollViewer.ScrollToRightEnd();

e.Handled = true;

break;

}

}

public static Visual GetDescendantByType(Visual element, Type type)

{

if (element == null) return null;

if (element.GetType() == type) return element;

Visual foundElement = null;

if (element is FrameworkElement)

(element as FrameworkElement).ApplyTemplate();

for (int i = 0;

i < VisualTreeHelper.GetChildrenCount(element); i++)

{

Visual visual = VisualTreeHelper.GetChild(element, i) as Visual;

foundElement = GetDescendantByType(visual, type);

if (foundElement != null)

break;

}

return foundElement;

}

}






Re: Windows Presentation Foundation (WPF) Make it scroll... (FlowDocumentScrollViewer)

PlaTyPuS8

wow! it's a little complicated.... you say it give side-effects when using preview actions which one

I can also use something other than FlowDocumentScrollViewer... I only need to display a FlowDocument in a Listbox! I try with the flowdocumentreader (in scroll view), but I've the same problem . If you have another idea to display the flowdocument (in a view like flowdocumentscrollviewer), I am very interested to hear it .

Thx for help!




Re: Windows Presentation Foundation (WPF) Make it scroll... (FlowDocumentScrollViewer)

Dr. WPF

> you say it give side-effects when using preview actions which one

Like I said, if you have controls within the FlowDocument that should respond to keyboard events like Left, Right, etc., these controls will not function properly if you handle the preview events on the ListBox.

> it's a little complicated....

Not really, it's just doing the exact same thing a ScrollViewer normally does in response to key events. This code can be seen by using reflection.

> If you have another idea to display the flowdocument (in a view like flowdocumentscrollviewer), I am very interested to hear it.

All of the derivatives of DocumentViewerBase handle the scroll keys directly so they do not bubble up to the ListBox. Even if they did, you would not get the behavior you want because a ListBox with an ItemsPanel that implements IScrollInfo provides "per item" scrolling. It will not scroll the document content. It will move to the next ListBox item. This is why I used the Preview events to do "per line" scrolling.

I don't think you're going to find an element that lets you view the FlowDocument within a ListBox *and* still get the scroll support you desire. The only possible option would be a RichTextBox, but I'm guessing you don't want the document to be editable. With a RichTextBox, as soon as you set IsReadOnly to true, you will lose the behavior that scrolls the content into view.

I wish I had some other ideas, but I think you've got too many competing interests. Sad You will either have to get rid of the ListBox or use the preview events.






Re: Windows Presentation Foundation (WPF) Make it scroll... (FlowDocumentScrollViewer)

PlaTyPuS8

hi Dr. !

Thx for your answer. At first, I think it would be possible to catch the MouseWheel on the FlowDocument and give it to the listbox.... but I don't find a solution to do it!

Here is my solution using the code you provided :

Code Block

<ListBox IsSynchronizedWithCurrentItem="True"
Margin="97,100,137,172"
PreviewMouseWheel="ListBox_PreviewMouseWheel"
ScrollViewer.CanContentScroll="False">


Code Block

private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
// make sure we have a reference to the ListBox's ScrollViewer

if (_listboxScrollViewer == null)
{
_listboxScrollViewer = GetDescendantByType(
sender as Visual, typeof(ScrollViewer)) as ScrollViewer;
}

if (_listboxScrollViewer == null) return;

_listboxScrollViewer.ScrollToVerticalOffset(_listboxScrollViewer.VerticalOffset - e.Delta);
}


Thx for your help Dr. WPF!

@++