Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何防止滑块因异步绑定而跳转?_C#_Wpf_Mvvm - Fatal编程技术网

C# 如何防止滑块因异步绑定而跳转?

C# 如何防止滑块因异步绑定而跳转?,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个滑块,它绑定到一个具有慢速getter和setter的属性。由于UI需要响应,因此绑定具有属性IsAsync。但当我拖动滑块时,它会在光标和0之间跳转(默认值FallbackValue) 是否有人知道如何防止这种行为,如何禁用回退值 XAML: 只是不要在属性内调用阻塞操作,它们不适用于此 正常绑定该值,并在命令中查询/验证其输入 <i:Interaction.Triggers> <i:EventTrigger EventName="ValueChanged"&

我有一个滑块,它绑定到一个具有慢速getter和setter的属性。由于UI需要响应,因此绑定具有属性
IsAsync
。但当我拖动滑块时,它会在光标和0之间跳转(默认值
FallbackValue

是否有人知道如何防止这种行为,如何禁用
回退值

XAML:


只是不要在属性内调用阻塞操作,它们不适用于此

正常绑定该值,并在命令中查询/验证其输入

<i:Interaction.Triggers>
    <i:EventTrigger EventName="ValueChanged">
        <cmd:EventToCommand Command="{Binding UpdateSomethingCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

不需要使getter异步,只需存储(缓存)最后一个值。 您可以正常绑定到属性并自己实现异步更新:

视图:

其思想是:记录滑块值的变化,并只执行最后一个

录制是通过将任务与
ContinueWith
链接来完成的。刚完成任务时,每次更改
都将创建一个新任务

我不知道是否有一种方法可以检查当前任务是否有继续,因此使用了
\u id
。当
\u id==id
任务是链中的最后一个时(否则任务什么也不做,因为有更多的实际更新)

第二个
如果使用
检查工作后的是否有更多任务,并防止值更改回原来的值(您当前的效果)。如果您的工作返回的值与设置的值不同,则需要此通知。否则,如果将第二个
完全删除(不需要)


请注意
延迟
在绑定中,它将减少任务数量(如果没有它,滑块的一次移动可能会产生几十个任务)。

我不知道这个解决方案是否可以被视为“纯MVVM”,但让我们提出它,看看它是否适合您。 首先,我们定义一个滑块并订阅Thumb.DragCompleted事件。我们还将UpdateSourceTrigger设置为explicit:

<Slider Maximum="100" Minimum="0" Width="300" x:Name="slid" Thumb.DragCompleted="MySlider_DragCompleted" >
        <Slider.Value>
            <Binding Path="Value" UpdateSourceTrigger="Explicit"/>
        </Slider.Value>
</Slider>

总而言之,我们在这里所做的只是在“滑动”过程完成后才进行绑定(获取/设置滑块值)。

是的,我在标记中提到过示例:不要在属性中放置阻塞操作。当滑块更改命令时,使用交互性触发器调用命令values@Tseng没有帮助。它挡不住!因此,属性存在。我只是有了这个属性。@Andy:它不是阻止UI线程,而是阻止vm本身。由于它没有激发OnPropertyChanged值,UI没有收到关于新值的通知,因此会返回。只需设置值,然后通过命令更正/验证即可(或者通过命令传递当前值并在那里进行验证,如果ViewModel中的successfulProperties不应该做任何会导致延迟的事情,则设置它。这就是MVVM模式的全部要点。任何需要计算值的工作都应该在设置属性值之前完成,或者,作为最后的手段,在e setter仍然在阻塞,您正在调用
.Result
。并且您不能使用
wait
在那里当您调用
Task…Result
时,它阻塞setter,因为它等待任务完成。您是对的,没有注意到
100 ms
的行为。让我重新考虑一下。
<i:Interaction.Triggers>
    <i:EventTrigger EventName="ValueChanged">
        <cmd:EventToCommand Command="{Binding UpdateSomethingCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>
public ICommand UpdateSomethingCommand { get; } = new RelayCommand(UpdateSomething);
private async void UpdateSomething() 
{
    await SomeLengthlyCallOrValidation(this.SliderValue);
}
<Slider Value="{Binding Value, Delay=100}" Maximum="..." />
Task _task = Task.Run(() => { }); // Task.CompletedTask in 4.6
volatile int _id;

double _value;
public double Value
{
    get { return _value; }
    set
    {
        _value = value;
        OnPropertyChanged();
        // task
        var id = ++_id; // capture id
        _task = _task.ContinueWith(o =>
        {
            if (_id == id)
            {
                Thread.Sleep(1000); // simulate work
                // this is optional if value stays the same
                if (_id == id)
                {
                    _value = value + 10; // simulate different value
                    Dispatcher.InvokeAsync(() => OnPropertyChanged(nameof(Value)));
                }
            }
        });
    }
}
<Slider Maximum="100" Minimum="0" Width="300" x:Name="slid" Thumb.DragCompleted="MySlider_DragCompleted" >
        <Slider.Value>
            <Binding Path="Value" UpdateSourceTrigger="Explicit"/>
        </Slider.Value>
</Slider>
private void MySlider_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{     
    BindingExpression be = slid.GetBindingExpression(Slider.ValueProperty);
    be.UpdateSource();
}