【问题标题】:How do I listen to UWP Xaml Slider manipulation start/end events?如何收听 UWP Xaml Slider 操作开始/结束事件?
【发布时间】:2018-02-16 19:16:39
【问题描述】:

我应该在 UWP Xaml 滑块上监听哪些事件以确定用户何时开始和结束操作。

当您有一个表示某些不断变化的应用状态(例如,动画时间)的滑块并且您希望在用户与滑块交互时暂停更新时,此功能非常重要。

已针对 WPF 和 Windows Phone 回答了此问题,但未针对 UWP 回答。对于 UWP,其他解决方案不起作用或不完整。

【问题讨论】:

    标签: events uwp slider uwp-xaml


    【解决方案1】:

    您需要监听来自 Slider 模板的几个元素的交互事件:Thumb 和 Container。这是因为用户可以通过单击和拖动来直接操纵拇指,而且他们也可以单击滑块上的任何位置,拇指会跳到那个位置(即使看起来你正在操纵拇指,实际上拇指是每次鼠标移动时都会重新定位 - 您仍在与容器交互)。

    有几个注意事项:

    • thumb 和容器都处理它们的输入事件而不传递它们,因此您需要使用附加 RoutedEvent 处理程序的 AddHandler 方法,以便获取已经处理的事件。

    • 您需要在应用控件模板后附加事件处理程序,这意味着您需要将 Slider 子类化以覆盖受保护的方法。

    此处介绍了 RoutedEvent 处理程序信息:https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/events-and-routed-events-overview#registering-handlers-for-already-handled-routed-events

    以下 SliderEx 类添加了一些事件,可用于检测用户何时开始/结束与滑块的交互:

    public class SliderEx : Slider
    {
        public event EventHandler SliderManipulationStarted;
        public event EventHandler SliderManipulationCompleted;
        public event EventHandler SliderManipulationMoved;
        private bool IsSliderBeingManpulated
        {
            get
            {
                return this.isContainerHeld || this.isThumbHeld;
            }
        }
    
    
        private bool isThumbHeld = false;
        private bool isContainerHeld = false;
    
        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var thumb = base.GetTemplateChild("HorizontalThumb") as Thumb;
            if (thumb == null)
            {
                thumb = base.GetTemplateChild("VerticalThumb") as Thumb;
            }
            if (thumb != null)
            {
                thumb.DragStarted += this.Thumb_DragStarted;
                thumb.DragCompleted += this.Thumb_DragCompleted;
                thumb.DragDelta += this.Thumb_DragDelta;
            }
    
            var sliderContainer = base.GetTemplateChild("SliderContainer") as Grid;
            if (sliderContainer != null)
            {
                sliderContainer.AddHandler(PointerPressedEvent, 
                    new PointerEventHandler(this.SliderContainer_PointerPressed), true);
                sliderContainer.AddHandler(PointerReleasedEvent, 
                    new PointerEventHandler(this.SliderContainer_PointerReleased), true);
                sliderContainer.AddHandler(PointerMovedEvent, 
                    new PointerEventHandler(this.SliderContainer_PointerMoved), true);
            }
        }
    
        private void SliderContainer_PointerMoved(object sender, 
            Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            this.InvokeMove();
        }
    
        private void SliderContainer_PointerReleased(object sender, 
            Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            this.SetContainerHeld(false);
        }
    
        private void SliderContainer_PointerPressed(object sender, 
            Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            this.SetContainerHeld(true);
        }
    
        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            this.InvokeMove();
        }
    
        private void Thumb_DragCompleted(object sender, DragCompletedEventArgs e)
        {
            this.SetThumbHeld(false);
        }
    
        private void Thumb_DragStarted(object sender, DragStartedEventArgs e)
        {
            this.SetThumbHeld(true);
        }
    
        private void SetThumbHeld(bool held)
        {
            bool wasManipulated = this.IsSliderBeingManpulated;
            this.isThumbHeld = held;
            this.InvokeStateChange(wasManipulated);
        }
    
        private void SetContainerHeld(bool held)
        {
            bool wasManipulated = this.IsSliderBeingManpulated;
            this.isContainerHeld = held;
            this.InvokeStateChange(wasManipulated);
        }
    
        private void InvokeMove()
        {
            this.SliderManipulationMoved?.Invoke(this, EventArgs.Empty);
        }
    
        private void InvokeStateChange(bool wasBeingManipulated)
        {
            if (wasBeingManipulated != this.IsSliderBeingManpulated)
            {
                if (this.IsSliderBeingManpulated)
                {
                    this.SliderManipulationStarted?.Invoke(this, EventArgs.Empty);
                }
                else
                {
                    this.SliderManipulationCompleted?.Invoke(this, EventArgs.Empty);
                }
            }
        }
    }
    

    【讨论】:

    • 如果您已经回答了自己的问题,请不要忘记通过关注here关闭此主题
    • 干得好,成功了!实际上,我只需要 sliderContainer 处理程序。
    • @Chris Caulfield 操作完成后如何获取指针的位置?
    • 其实Manipulation*是正确的做法:stackoverflow.com/a/57456981/3590849
    猜你喜欢
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    相关资源
    最近更新 更多