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

Viewed 39146

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)

4 Answers

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);

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;
}

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

Related