【问题标题】:WPF - how not to update a slider's value on draggingWPF - 如何在拖动时不更新滑块的值
【发布时间】:2016-04-14 16:46:10
【问题描述】:

您可能会说它是 How to stop update value of slider while dragging it? 的副本,但老实说,2011 年的解决方案对我不起作用(甚至评论其他用户接受的答案),其他答案与我无关.所以请大家耐心等待。

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

<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 这里的答案对我没有帮助,因为它是数据模板中生成的滑块,事件与我无关。

【问题讨论】:

  • “其他答案与我无关”。那可能是因为你没有仔细观察。如果将 FrameworkPropertyMetadataOptions.BindsTwoWayByDefault 添加到依赖属性元数据中,derived Slider with FinalValue property 将完美运行。

标签: c# wpf


【解决方案1】:

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

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

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

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

我在仅覆盖其他答案中建议的 OnThumbDragCompleted 方法时遇到问题。这意味着只有在通过拖动拇指操纵Slider 时,更改才会传播。例如,如果您单击拇指旁边的按钮,您的住宿将不会收到通知。基本上我要说的是,如果您要使用从 Slider 派生的解决方案,则必须确保同步 Value 和 FinalValue 的值。

【讨论】:

  • 你确定它应该有效吗?我正在使用 WPF 4.5,它显示“错误 1 ​​在 'Binding' 类型中找不到属性 'Delay'。”
  • @GuyBen-Moshe 它应该可以工作。我认为它需要 .NET Framework 4.5 或更高版本,而且我记得 this answer 中的 cmets 你没有使用它。
  • 我收到了关于 WPF 升级的通知(因为我在回答后向我的老板提出了要求),我会调查一下,谢谢 :)
【解决方案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);
    }
}

【讨论】:

  • 正如@Clemes 在 cmets 中指出的那样,this answer 将被证明更加有用。只是有一个不同的FinalValue,它只会在OnThumbDragCompleted上改变
  • @Jcl 我不同意。另一个答案是缺少关键的(在我看来)功能 - 请参阅我的评论。
  • @Grx70 在FinalValue 更改时设置Value 的问题(在dp 上有PropertyChangedCallback),在我看来,仍然比这更好,但你是对的,需要一些调整。我通常从不将 SO 答案作为最终答案,只是提示该怎么做:-)
  • @Jcl 这是真的,我同意其他解决方案在一般情况下更通用,所以我什至没有说这个解决方案更好。它只是对问题采取了不同的方法。
【解决方案3】:

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

【讨论】:

  • 后面的代码发生在不同的类(不是window类)中,因为它绑定了数据模板,是否仍然可以这样做?
  • @GuyBen-Moshe 没有什么可以阻止您将属性添加到您的视图模型,并在鼠标按下时执行((MyViewModel)AudioSlider.DataContext).SendPackets = true; 之类的操作,或其他操作
【解决方案4】:

我完全同意 Noctis,此外您可以使用获取 Action&lt;bool&gt; 的行为,并且使用该操作和 mousedown/mouseup 事件可以发出信号,如果您可以发送数据包。此外,您可以在 mouseup 上处理最终值,将该值传递给视图模型,更新 AudioValue 指示器并发送您需要的数据包(您需要另一个行为动作,例如Action&lt;bool, double&gt;,如果您可以发送数据包和double 用于 AudioValue 本身)。

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

【讨论】:

    猜你喜欢
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多