wpf 如何用鼠标滚轮改变滑块的值?

i2byvkas  于 2023-10-22  发布在  其他
关注(0)|答案(3)|浏览(146)

我想将Slider的值更改为鼠标滚轮:当我向上滚动时,Slider'sValue属性应该增加,当我向下滚动时,它应该减少。
行为应该独立于鼠标位置或当前焦点。
解决方案最好使用绑定并且仅是XAML,但代码隐藏解决方案也足够了。

olqngx59

olqngx591#

您可以使用一个附加的行为,将父WindowPreviewMouseWheel事件挂接起来,并设置Slider的值。
使用附加行为使您能够封装功能并将其重用于任何Slider控件,而无需修改每个视图的代码隐藏文件。
这里有一个例子供你参考。

public class MouseWheelBehavior
{
    public static double GetValue(Slider slider)
    {
        return (double)slider.GetValue(ValueProperty);
    }

    public static void SetValue(Slider slider, double value)
    {
        slider.SetValue(ValueProperty, value);
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.RegisterAttached(
        "Value",
        typeof(double),
        typeof(MouseWheelBehavior),
        new UIPropertyMetadata(0.0, OnValueChanged));

    public static Slider GetSlider(UIElement parentElement)
    {
        return (Slider)parentElement.GetValue(SliderProperty);
    }

    public static void SetSlider(UIElement parentElement, Slider value)
    {
        parentElement.SetValue(SliderProperty, value);
    }

    public static readonly DependencyProperty SliderProperty =
        DependencyProperty.RegisterAttached(
        "Slider",
        typeof(Slider),
        typeof(MouseWheelBehavior));

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Slider slider = d as Slider;
        slider.Loaded += (ss, ee) =>
        {
            Window window = Window.GetWindow(slider);
            if (window != null)
            {
                SetSlider(window, slider);
                window.PreviewMouseWheel += Window_PreviewMouseWheel;
            }
        };
        slider.Unloaded += (ss, ee) => 
        {
            Window window = Window.GetWindow(slider);
            if(window != null)
            {
                SetSlider(window, null);
                window.PreviewMouseWheel -= Window_PreviewMouseWheel;
            }
        };
    }

    private static void Window_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        Window window = sender as Window;
        Slider slider = GetSlider(window);
        double value = GetValue(slider);
        if(slider != null && value != 0)
        {
            slider.Value += slider.SmallChange * e.Delta / value;
        }
    }
}

使用方法:

<Slider local:MouseWheelBehavior.Value="120" />
k2arahey

k2arahey2#

我找不到使用绑定或XAML的方法,但这个相当简单的代码隐藏解决方案可以工作:

MyPanel.PreviewMouseWheel += (sender, e)
    => MySlider.Value += MySlider.SmallChange * e.Delta / 120;

一些注意事项:

  • MyPanel可以是任何Control。当鼠标在使用滚轮时位于此Control上方时,将触发该事件。
  • 您可以使用MouseWheelPreviewMouseWheel事件。如果有其他控件处理MouseWheel事件(如ScrollViewer),则后者更方便。
  • 当您将鼠标滚轮向上移动一个刻度时,Delta将保持值120。所以你必须除以这个值才能得到预期的行为。
  • 如果MySlider.Value绑定到代码中的某个属性,则应调整该属性的值,而不是直接更改Slider
doinxwow

doinxwow3#

虽然accepted answer * 确实 * 工作,但它有一些严重的缺点,使其在我的情况下无法使用:

  • 仅适用于单个Slider控件(以最后创建的为准)
  • 无论鼠标实际位于何处(只要鼠标位于窗口上方),都可以正常工作
  • 价值变化不精确

另一种没有这些问题的方法是使用官方的Microsoft.Xaml.Behaviors.Wpf nuget包:

C#

public class MouseWheelSliderBehavior : Behavior<Slider>
{
    public double Amount
    {
        get => (double)GetValue(AmountProperty);
        set => SetValue(AmountProperty, value);
    }

    public static readonly DependencyProperty AmountProperty
        = DependencyProperty.RegisterAttached(
            nameof(Amount), 
            typeof(double), 
            typeof(MouseWheelSliderBehavior), 
            new UIPropertyMetadata(0.0));

    private void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (Amount == 0.0) return;
        Slider slider = (Slider)sender;
        if (e.Delta > 0)
        {
            slider.Value += Amount;
        }
        else
        {
            slider.Value -= Amount;
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.PreviewMouseWheel += this.AssociatedObject_PreviewMouseWheel;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.PreviewMouseWheel -= this.AssociatedObject_PreviewMouseWheel;
    }
}

XAML

添加以下命名空间:

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

然后,使用行为:

<Slider>
    <i:Interaction.Behaviors>
        <local:MouseWheelSliderBehavior Amount="1" />
    </i:Interaction.Behaviors>
</Slider>

无论您将Amount设置为什么,都是滑块值将改变的量。

相关问题