Activate horizontal scrolling with mouse on ListView

后端 未结 4 1119
不思量自难忘°
不思量自难忘° 2020-12-18 13:30

I\'ve got a custom horizontal ListView with custom ScrollViewer inside it\'s template (created with Blend). I want it to scroll horizontally when using mouse scrolling wheel

4条回答
  •  再見小時候
    2020-12-18 14:01

    This should be done with a Behavior for greater reusability. Also, the logic from ZSH is redundant and could be simplified. Here's my code:

    /// 
    /// Allows an  to scroll horizontally by listening to the
    ///  event of its internal .
    /// 
    public class HorizontalScrollBehavior : Behavior
    {
        /// 
        /// A reference to the internal ScrollViewer.
        /// 
        private ScrollViewer ScrollViewer { get; set; }
    
        /// 
        /// By default, scrolling down on the wheel translates to right, and up to left.
        /// Set this to true to invert that translation.
        /// 
        public bool IsInverted { get; set; }
    
        /// 
        /// The ScrollViewer is not available in the visual tree until the control is loaded.
        /// 
        protected override void OnAttached()
        {
            base.OnAttached();
    
            AssociatedObject.Loaded += OnLoaded;
        }
    
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            AssociatedObject.Loaded -= OnLoaded;
    
            ScrollViewer = VisualTreeHelpers.FindVisualChild(AssociatedObject);
    
            if (ScrollViewer != null)
            {
                ScrollViewer.PreviewMouseWheel += OnPreviewMouseWheel;
            }
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
    
            if (ScrollViewer != null)
            {
                ScrollViewer.PreviewMouseWheel -= OnPreviewMouseWheel;
            }
        }
    
        private void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            var newOffset = IsInverted ?
                ScrollViewer.HorizontalOffset + e.Delta :
                ScrollViewer.HorizontalOffset - e.Delta;
    
            ScrollViewer.ScrollToHorizontalOffset(newOffset);
        }
    }
    

    You'll need to add the following references: System.Windows, System.Windows.Controls, System.Windows.Input, and you may need to get the Blend SDK NuGet package, and find and reference the System.Windows.Interactivity DLL in the Assemblies Extensions section.

    Use this for VisualTreeHelpers:

    public class VisualTreeHelpers
    {
        /// 
        /// Return the first visual child of element by type.
        /// 
        /// The type of the Child
        /// The parent Element
        public static T FindVisualChild(DependencyObject obj) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is T)
                    return (T)child;
                else
                {
                    T childOfChild = FindVisualChild(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
         }
    }
    

    Reference: https://codereview.stackexchange.com/questions/44760/is-there-a-better-way-to-get-a-child

    Note that it is NOT the same as VisualTreeHelper in Windows.System.Media.

    Here's how to use it in XAML:

    
        
            
        
    
    

    Where the i namespace is declared as xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" and

    behaviors is declared as

    xmlns:behaviors="clr-namespace:MyNamespace"

    where MyNamespace is the namespace that contains the HorizontalScrollBehavior class.

提交回复
热议问题