C# WPF-如何不更新滑块';s拖动时的值

C# WPF-如何不更新滑块';s拖动时的值,c#,wpf,C#,Wpf,你可能会说这是一个复制品,但老实说,这个解决方案是从2011年开始的,只是对我不起作用(甚至对其他用户接受的答案发表了评论),而其他答案与我无关。所以请大家耐心点 这就是我的问题:我有一个绑定到如下值的滑块: <Slider Name="AudioSlider" Value="{Binding AudioValue}" Grid.Column="1" Grid.Row="1" Height="30" SmallChange="1" Ma

你可能会说这是一个复制品,但老实说,这个解决方案是从2011年开始的,只是对我不起作用(甚至对其他用户接受的答案发表了评论),而其他答案与我无关。所以请大家耐心点

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

<Slider Name="AudioSlider" Value="{Binding AudioValue}" 
        Grid.Column="1"    Grid.Row="1"    Height="30" 
        SmallChange="1"    Maximum="100" 
        IsSnapToTickEnabled="True"                                      
        IsMoveToPointEnabled="True"/>
如您所见,每次值更改时,我都会发送一个数据包,当它在拖动时更新值时,它只是在服务器上滥发值,这是必须防止的

我曾尝试将滑块绑定到函数(mouseUp),但无法通过这种方式获得值

你知道我能做什么吗

非常感谢

编辑:


这里的答案对我没有帮助,因为它是数据模板中生成的滑块,事件与我无关。

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

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

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);
    }
}

我完全同意Noctis,此外,您可以使用获得
操作的行为,并且使用该操作和mousedown/mouseup事件可以发出是否可以发送数据包的信号。此外,您可以在mouseup上处理最终值,将该值传递给viewmodel,更新AudioValue指示符并发送所需的数据包(您需要行为中的另一个操作,如
操作
,其中布尔值表示是否可以发送数据包,而double表示AudioValue本身)

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

如果您使用的是WPF 4.5,您只需使用

Value="{Binding AudioValue, Delay=500}"
这将限制更改通知。 如果用户快速拖动滑块,这将“重置”内部计时器,并将删除挂起的通知。当用户停止并且500毫秒延迟结束时,它将调用setter方法一次

有很多方法可以做到这一点,所以这只是一个建议。 您可以在VM中使用Rx及其节流方法来实现这一点。这与
绑定
延迟
属性基本相同


正如其他答案中所建议的那样,我有一个问题,就是只覆盖umbdragcompleted
方法。这意味着只有通过拖动拇指操纵
滑块
,更改才会传播。例如,如果您单击拇指旁边,您的财产将不会得到通知。基本上,我想说的是,如果要使用从
滑块

派生的解决方案,则必须确保同步
最终值的值,因为后面的代码发生在不同的类(而不是窗口类)中,因为它与数据模板绑定,仍然可以这样做吗?@GuyBen Moshe没有任何东西阻止您将属性添加到viewmodel,并执行类似于
((MyViewModel)AudioSlider.DataContext)的操作在mousedown上,或者“其他答案与我无关”。那可能是因为你没有仔细看。如果将
FrameworkPropertyMetadataOptions.bindstwoway默认情况下
添加到依赖项属性元数据中,则此功能将非常有效。正如@Clemes在注释中所指出的,这将证明更加有用。只是有一个不同的
最终值
,它只会在umbdragcompleted上的
发生变化
@Jcl我不同意。另一个答案是缺少关键的(在我看来)功能-请看我的评论。@Grx70当
FinalValue
更改时设置
Value
的问题(dp上有一个
PropertyChangedCallback
),在我的观点中仍然比这更好,但你是对的,需要一些调整。我通常从不把这样的答案作为最终答案,只不过是关于如何做的提示:-)@Jcl这是真的,我同意另一种解决方案在一般情况下更通用,所以我甚至没有说这个解决方案更好。它只是在这个问题上采取了不同的方法。你确定它应该有效吗?我正在使用WPF 4.5,它说“错误1在类型“Binding”中找不到属性“Delay”。@GuyBen Moshe它应该可以工作。我想它需要.NET Framework 4.5或更高版本,我记得在你的评论中没有使用它。我收到了WPF升级的通知(因为我在回答后向我的老板提出了要求),我会调查的,谢谢:)
Value="{Binding AudioValue, Delay=500}"