WPF - 如何在拖动时更新滑块的值

时间:2016-01-10 08:30:22

标签: c# wpf

你可能会说它是How to stop update value of slider while dragging it?的副本,但老实说,解决方案是从2011年开始的,并没有为我工作(甚至评论了其他用户接受的答案),其他答案是&n #39;与我相关。所以请耐心等待。

这就是我的问题:我有一个滑块绑定到这样的值:

<Slider Name="AudioSlider" Value="{Binding AudioValue}" 
        Grid.Column="1"    Grid.Row="1"    Height="30" 
        SmallChange="1"    Maximum="100" 
        IsSnapToTickEnabled="True"                                      
        IsMoveToPointEnabled="True"/>

这就是价值:

        private double _audioValue;
        public double AudioValue
        {
            get { return _audioValue; }
            set
            {
                if (_audioValue == value)
                    return;
                _audioValue = value;
                SendPacket(cockpitType, (byte)Index.AudioSlider, (byte)_audioValue);
                OnPropertyChanged("AudioValue");
            }
        }

正如您所看到的,每次值发生变化时,我都会发送一个数据包,当它更新拖拽值时,它只是在服务器上发送垃圾邮件并且必须阻止它。

我试图将滑块绑定到一个函数(mouseUp),但我无法通过这种方式获取值。

任何想法我能做什么?

非常感谢。

编辑:

WPF: Slider with an event that triggers after a user drags的答案对我没有帮助,因为它在数据模板中生成了滑块,事件与我无关。

4 个答案:

答案 0 :(得分:10)

如果您使用的是WPF 4.5,则可以使用

Value="{Binding AudioValue, Delay=500}"

将限制更改通知。 如果用户快速拖动滑块,则会重置&#34;重置&#34;内部计时器,将删除待处理的通知。当用户停止并且500毫秒延迟结束时,它将调用您的setter方法一次。

有很多方法可以做到这一点,所以这只是一个建议。 您可以在VM中使用Rx及其Throttle方法执行此操作。这与Binding的{​​{1}}属性基本相同。

我在覆盖其他答案中建议的Delay方法时遇到问题。这意味着只有在拖动拇指操纵OnThumbDragCompleted时才会传播更改。例如,如果您单击拇指旁边的某个属性,您的属性就不会得到通知。基本上我所说的是,如果你要使用从Slider派生的解决方案,你必须确保同步ValueFinalValue的值。

答案 1 :(得分:2)

我建议创建自己的滑块继承自原始滑块,这将在拖动开始时清除绑定并在拖动完成后恢复它。这是一个例子:

public class CustomSlider : Slider
{
    private Binding SupressedBinding { get; set; }

    protected override void OnThumbDragStarted(DragStartedEventArgs e)
    {
        base.OnThumbDragStarted(e);
        var expression = BindingOperations.GetBindingExpression(this, ValueProperty);
        if (expression != null)
        {
            SupressedBinding = expression.ParentBinding;
            //clearing the binding will cause the Value to reset to default,
            //so we'll need to restore it
            var value = Value;
            BindingOperations.ClearBinding(this, ValueProperty);
            SetValue(ValueProperty, value);
        }
    }

    protected override void OnThumbDragCompleted(DragCompletedEventArgs e)
    {
        if (SupressedBinding != null)
        {
            //again, restoring the binding will cause the Value to update to source's
            //value (which is "out of date" by now), so we'll need to restore it
            var value = Value;
            BindingOperations.SetBinding(this, ValueProperty, SupressedBinding);
            SetCurrentValue(ValueProperty, value);
            SupressedBinding = null;
        }
        base.OnThumbDragCompleted(e);
    }
}

答案 2 :(得分:1)

创建一个布尔属性,在mousedown上设置为false,在mouseup上设置为true,并且在您的属性中,仅当该属性为true时才发送数据包?

答案 3 :(得分:0)

我完全同意Noctis,此外你可以使用获得Startup的行为,并且使用该动作和mousedown / mouseup事件可以发出信号,告知你是否可以发送数据包。此外,您可以处理mouseup的最终值,将该值传递给viewmodel,更新AudioValue指示器并发送您需要的数据包(您需要在行为中执行其他操作,如Action<bool>,其中boolean signalize如果您可以发送packet和double用于AudioValue本身)。

如果需要有关代码的帮助,我很乐意提供帮助。 问候。