Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent scrolling when mouse enters WPF ComboBox dropdown

When a ComboBox has a large number of items, its dropdown will become scrollable. When the user invokes this dropdown, and moves the mouse cursor to enter the bounds of the dropdown from the bottom, the dropdown immediately scrolls one or more items down the list (from goobering: also happens when exiting the bounds via the bottom edge).

This scrolling is not intuitive, as the list does not scroll upwards when entering the bounds from the top.

How can we disable the automatic scrolling behavior?

In Visual Studio this behavior can be observed via the member dropdown on the code editor's navigation bar (CTRL+F2).

like image 367
JoeGaggler Avatar asked Apr 14 '15 22:04

JoeGaggler


3 Answers

One way to solve this is to use a Behaviour (or rather behaviour-like Attached Property) to subscribe to the RequestBringIntoView event of the ComboBoxItems and then set the RequestBringIntoViewEventArgs.Handled to true. This can also be done on a small scale using an EventSetter and codebehind.

 <Style TargetType="ComboBoxItem">                    
     <EventSetter Event="RequestBringIntoView" Handler="OnRequestBringIntoView"/>
 </Style>

private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
    //Allows the keyboard to bring the items into view as expected:
    if (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up))
        return;            

    e.Handled = true;            
}

Edit

I found that you can get the same effect by handling the RequestBringIntoView event on the ItemsPanel rather than the items themselves. But same result:

<ComboBox.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel RequestBringIntoView="OnRequestBringIntoView"/>
    </ItemsPanelTemplate>
</ComboBox.ItemsPanel>
like image 73
Andrew Hanlon Avatar answered Oct 21 '22 04:10

Andrew Hanlon


From what I can tell this seems to be caused by the items at the bottom of the light being "partially displayed", where an item is truncated by the container. When the mouse goes over a partial item like this WPF scrolls the entire item in to view, which can sometimes leave another partial item at the bottom.

In Winforms this can be fixed by setting the .IntegralHeight, but no such property exists in WPF from what I can tell. If all the items in your combobox have the same height you could bind the height of the list of the combobox to a multiple of the item height, for example, display 10 x 20px tall items, set it to 200.

like image 30
Bradley Uffner Avatar answered Oct 21 '22 05:10

Bradley Uffner


The selected answer from Andrew Hanlon prevents the list from scrolling to the selected item when opened.

I had to add this into the event handler ("list" is the ComboBox):

private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
    //Allows the keyboard to bring the items into view as expected:
    if (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up))
        return;

    // Allows to bring the selected item into view:
    if (((ComboBoxItem)e.TargetObject).Content == list.SelectedItem)
        return;

    e.Handled = true;
}
like image 38
dada Avatar answered Oct 21 '22 04:10

dada