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).
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>
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With