wpf combobox how to handle PreviewMouseWheel

29 views Asked by At

I want to add a handler for the MouseWheel to the ComboBox, but I don't know how.

The reason is that I have scrolling problems with a ComboBox inside DataGrid inside ScrollViewer, see here, and I would like to experiment. I already have code to handle the MouseWheel for the ScrollViewer, and for the DataGrid, but not yet for the ComboBox.

<ComboBox PreviewMouseWheel="theComboBox_PreviewMouseWheel"

code behind:

    private void theScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (sender is ScrollViewer scrollView)
        {
            scrollView.UpdateLayout();
            scrollView.ScrollToVerticalOffset(scrollView.VerticalOffset - e.Delta);
            e.Handled = true;
        }            
    }

    private void theDataGrid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var args = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
        args.RoutedEvent = ScrollViewer.MouseWheelEvent;
        theScrollViewer.RaiseEvent(args);
    }

    /// <summary>
    /// The hypothetical scroll event handler, on the ComboBox,
    /// to make the ComboBox scrollable
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void theComboBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (sender is ComboBox cb)
        {
            var args = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            args.RoutedEvent = ScrollViewer.MouseWheelEvent;
            //cb.ItemsPanel.RaiseEvents(args);//cb has no such property
            //cb.ScrollToVerticalOffset(cb.VerticalOffset - e.Delta);//cb has no such property
            //e.Handled = true;
        }
    }
1

There are 1 answers

1
mm8 On BEST ANSWER

You can get a reference to the ComboBox's internal ScrollViewer using the VisualTreeHelper class and then access its properties and methods to set the offset:

private void theComboBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    if (sender is ComboBox cb && e.OriginalSource is DependencyObject depObj)
    {
        ScrollViewer scrollViewer = FindParent<ScrollViewer>(depObj);
        ...
    }
}

private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
    var parent = VisualTreeHelper.GetParent(dependencyObject);
    if (parent == null)
        return null;

    var parentT = parent as T;
    return parentT ?? FindParent<T>(parent);
}