C# - how do I prevent mousewheel-scrolling in my combobox?
Asked Answered
F

4

72

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)

Fanning answered 10/12, 2009 at 18:21 Comment(0)
B
131

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);
Because answered 10/12, 2009 at 18:34 Comment(5)
Works perfectly, thanks! Sidenote: if you want scrolling to still apply when the ComboBox is dropped down, just add the lines: "ComboBox control = (ComboBox)sender;" and "if (!control.DroppedDown)" before the "((HandledMouseEventArgs)e).Handled = true" line.Katykatya
This currently doesn't work with Mono. bugzilla.xamarin.com/show_bug.cgi?id=25201Anaplasty
I know this is old, but I like this version right after InitializeComponent(); in the form constructor: comboBox1.MouseWheel += (o, e) => ((HandledMouseEventArgs)e).Handled = true;Molech
This also technique also works for comboboxes in WPF, but with the arguments object sender, System.Windows.Input.MouseWheelEventArgs e in the event handler, and you don't have to cast e to HandledMouseEventArgsFreakish
Just wanted to note that this also works with the NumericUpDown control.Milkmaid
C
8

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;
}
Cervix answered 29/8, 2018 at 16:24 Comment(0)
S
0

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;

Speer answered 8/10, 2015 at 7:21 Comment(0)
P
0

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

Philbert answered 10/10, 2019 at 15:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.