Reputation: 1896
I have a combobox and I want to prevent the user from scrolling through the items with the mousewheel.
Is there an easy way to do that?
(C#, VS2008)
Upvotes: 72
Views: 45908
Reputation: 40
I know this is old but if someone wants to do this in WinUI 3, MouseWheel
is not available, PointerWheelChanged
can be used in the same way as the other answers, however, it is not fired at times, I did not get deep into it, but if you open the DropDown
and then close it without focusing any other element the event does not get fired anymore until some other element gets focus.
I was able to make this work by setting ScrollViewer.VerticalScrollModeProperty
attached property to Disabled
by default on the ComboBox
, then I set it to Enabled
when the DropDown
gets opened and Disabled
when the DropDown
gets closed:
private void FieldComboBox_OnDropDownOpened(object? sender, object e)
{
ScrollViewer.SetVerticalScrollMode(ComboBox, ScrollMode.Enabled);
}
private void FieldComboBox_OnDropDownClosed(object? sender, object e)
{
ScrollViewer.SetVerticalScrollMode(ComboBox, ScrollMode.Disabled);
}
Edit: After further testing I found out that the problem I mentioned above is present in my solution as well, when the DropDown
gets closed the event does get fired in this case and the ScrollViewer.VerticalScrollModeProperty
does get set to Disabled
, however, scrolling still works on the ComboBox
until some other element receives focus. I worked around this by manually focusing some other element in the OnDropDownClosed
event.
Upvotes: 0
Reputation: 71
My Combobox's were placed inside a DataGrid [C#, WPF XAML] just like this:
<DataGrid x:Name="dgvFieldsMapping" Grid.Row="1" ItemsSource="{Binding}">
<DataGrid.Columns>
...
<DataGridTemplateColumn Width="*" Header="Destination Field" >
<DataGridTemplateColumn.CellTemplate >
<DataTemplate >
<ComboBox ItemsSource="{Binding Source={StaticResource CustomerDbFields}}" SelectedValue="{Binding destinationField, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ></ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
</DataGrid>
So whenever a DropDown was closed after selecting a Value, the Mousewheel would scroll that Combobox's Items and modify my Selection.
I ended up modifying my XAML to look like this:
<DataGrid x:Name="dgvFieldsMapping" Grid.Row="1" ItemsSource="{Binding}">
<DataGrid.Resources>
<Style x:Key="dgvComboBox_Loaded" TargetType="ComboBox">
<EventSetter Event="Loaded" Handler="dgvCombobox_Loaded" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
...
<DataGridTemplateColumn Width="*" Header="Destination Field" >
<DataGridTemplateColumn.CellTemplate >
<DataTemplate >
<ComboBox Style="{StaticResource dgvComboBox_Loaded}" ItemsSource="{Binding Source={StaticResource CustomerDbFields}}" SelectedValue="{Binding destinationField, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ></ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
</DataGrid>
And adding these lines in codebehind
public void dgvCombobox_Loaded(Object sender, RoutedEventArgs e)
{
((ComboBox)sender).DropDownClosed -= ComboBox_OnDropDownClosed;
((ComboBox)sender).DropDownClosed += new System.EventHandler(ComboBox_OnDropDownClosed);
}
void ComboBox_OnDropDownClosed(object sender, System.EventArgs e)
{
dgvFieldsMapping.Focus();
}
In this way I just move the Focus away from the ComboBox to the outer DataGrid after closing its corresponding DropDown, so I don't need to add any dummy FrameWorkElement
Upvotes: 0
Reputation: 6552
For WPF, handle the PreviewMouseWheel
event instead.
It would also be a good idea to consider ComboBox.IsDropDownOpen
so the user can still use mouse scroll if there are a lot of items in the selection when the ComboBox
is expanded.
Another thing is to apply the same behavior across the whole application.
I usually do all the above using the following code:
App.xaml
<Application.Resources>
<Style TargetType="ComboBox">
<EventSetter Event="PreviewMouseWheel" Handler="ComboBox_PreviewMouseWheel" />
</Style>
</Application.Resources>
App.xaml.cs
private void ComboBox_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
e.Handled = !((System.Windows.Controls.ComboBox)sender).IsDropDownOpen;
}
Upvotes: 9
Reputation: 21
I use another solution that also works on Mono.
Goal is to prevent accidentally scrolling (that is when the user is not looking at the comboBox when using the mouse wheel). If he / she scroll outside the visible portion of comboBox , the combo box should not scroll, otherwise it should.
My solution:
Place a read only text box outside the visible portion of the screen. In form_load I placed the line: hiddenTextbox.left = -100 ;
Set the focus to this text box when the mouse leaves the combo box using mouse leave event. In comboBox1_MouseLeave I placed the line: hiddenTextbox.focus();
Handle mouseWheel event: From1.MouseWheel += Form1_MouseWheel; textBoxHidden.MouseWheel += Form1_MouseWheel;
Upvotes: 0
Reputation: 53593
Use the MouseWheel event for your ComboBox:
void comboBox1_MouseWheel(object sender, MouseEventArgs e) {
((HandledMouseEventArgs)e).Handled = true;
}
Note: you'll have to create event in code:
comboBox1.MouseWheel += new MouseEventHandler(comboBox1_MouseWheel);
Upvotes: 133