如何在 MAUI 中使用鼠标滚轮更改滑块值?

How to implement changing slider value with mouse wheel in MAUI?

提问人:Corhal 提问时间:11/14/2023 更新时间:11/14/2023 访问量:78

问:

实际上问题出在标题中。
WPF 解决方案不适合(或者我还没有弄清楚如何调整它),而且我找不到任何其他具体内容。

此处的解决方案也无法调整,因为 Microsoft.Maui.Platform.MauiSlider 未转换为 Microsoft.Maui.Platform.ContentPanel。

C# .NET 滑块 毛伊岛 鼠标滚轮

评论

0赞 Riccardo Minato 11/14/2023
不是 WinUI 的大专家,但也许您可以从页面中的另一个视图(祖先?)获取 ContentPanel 强制转换,并在鼠标滚轮值更改时引发事件。
0赞 Corhal 11/14/2023
@Riccardo凑。因此,需要有目的地将 Slider 包装在另一个可以转换为 ContentPanel 的元素中?我不想仅仅为了实现鼠标滚轮支持而这样做。

答:

0赞 Liyun Zhang - MSFT 11/14/2023 #1

对于窗口,您可以为滑块添加事件。将以下代码放入 App 的构造函数中:PointerWheelChanged

        public App()
        {
            InitializeComponent();

            MainPage = new AppShell();
            Microsoft.Maui.Handlers.SliderHandler.Mapper.AppendToMapping(nameof(Slider), (handler, view) =>
            {
#if WINDOWS
                var winslider = view.Handler.PlatformView as Microsoft.UI.Xaml.Controls.Slider;
                winslider.PointerWheelChanged += (s,e) =>
                {
                    if (e.GetCurrentPoint(winslider).Properties.MouseWheelDelta>0)
                    {
                        view.Value++;
                    }
                    else
                    {
                        view.Value--;
                    }
                };
#endif
            });
        }

xaml 中的滑块为:。<Slider Minimum="0" Maximum="100"/>

但是我找不到Mac的解决方案。

更新:

如果您只想为特殊的滑块执行此操作。您可以从 App 的构造函数中删除上述代码。并使用它:

在 xaml 中:

<Slider Minimum="0" Maximum="100" x:Name="slider"/>

在 Page 的 OnHandlerChanged 方法中:

protected override void OnHandlerChanged()
    {
        base.OnHandlerChanged();
#if WINDOWS
        var winslider = slider.Handler.PlatformView as Microsoft.UI.Xaml.Controls.Slider;
        winslider.PointerWheelChanged += (s,e) =>
        {
            if (e.GetCurrentPoint(winslider).Properties.MouseWheelDelta>0)
            {
                slider.Value++;
            }
            else
            {
                slider.Value--;
            }
        };
#endif
    }

这仅适用于 .x:Name="slider"

评论

0赞 Corhal 11/14/2023
非常感谢,它真的很有效。但是,我是否正确理解这是 Slider 类所有元素的通用方法?如果是这样,如果有几个这样的元素并且它们的行为应该不同怎么办?
0赞 Liyun Zhang - MSFT 11/14/2023
对不起,我听不懂你的意思。你的意思是你想让所有的滑块都可以使用滚轮吗?如果是这样,则可以使用 并添加 的事件。@Corhal<Slider x:Name="slider"/>slider.Handler.PlatformView
0赞 Corhal 11/14/2023
据我了解,将为 Slider 类的每个元素调用 AppendToMapping 方法中指定的 Action。如果有两个,则该操作将被调用两次。这就是为什么出现了问题:为了正确定义其行为的方法,它被调用了哪个特定元素。您在注释中的建议(如果我理解正确的话),通过元素名称,将导致事件处理程序重复注册(添加)。
1赞 Corhal 11/14/2023
增强型解决方案并不完全是理想需要的。例如,假设有两个 Slider 元素,但它们应该以不同的方式更改每个单位鼠标滚轮移动的值。例如,第一个步长为 2,第二个步长为 4。因此,我们需要了解哪个元素具有事件。但是我已经解决了这个问题,所以再次感谢。
1赞 Corhal 11/14/2023
在下面查看我的答案,这是我需要的简化版本。添加它是为了不进一步夸大评论。
1赞 Corhal 11/14/2023 #2

根据受人尊敬的张丽云的回答,我为几个 Slider 元素形成了一个解决方案:

public MainPage()
{
    InitializeComponent();

    Microsoft.Maui.Handlers.SliderHandler.Mapper.AppendToMapping(nameof(Slider), (handler, view) =>
    {
#if WINDOWS
        Microsoft.UI.Xaml.Controls.Slider? winSlider = view.Handler?.PlatformView as Microsoft.UI.Xaml.Controls.Slider;

        if (winSlider != null)
        {
            winSlider.PointerWheelChanged += (s, e) =>
            {
                int step = 1;

                switch(handler)
                {
                    case slider1.Handler:
                        step = 2; //here you can replace a fixed value with a field or property
                        break;
                    case slider2.Handler;
                        step = 4; //here you can replace a fixed value with a field or property
                        break;
                }

                view.Value += e.GetCurrentPoint(winSlider).Properties.MouseWheelDelta / 120 * step;
            };
        }
#endif
    });
}

其中 slider1 和 slider1 元素在 XAML 布局中声明为(示例):

<Slider x:Name="slider1"/>
<Slider x:Name="slider2"/>