在双向数据绑定中在非UI线程上调用源属性更新 [英] Invoking source property update on a non-UI thread in two-way data binding

查看:37
本文介绍了在双向数据绑定中在非UI线程上调用源属性更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在源(CLR属性)和目标(UI控件属性)之间建立了WPF双向数据绑定.现在,无论何时更新目标属性,我都想更新非UI线程(而不是Dispatcher线程)上的source属性.在我的应用程序中,我正在使用Rx(响应式扩展)调度程序,因此,我计划提供一个Rx调度程序进行执行.

Suppose I have a WPF two-way data binding between a source (CLR property) and a destination (UI control property). Now anytime the destination property is updated, I want to update the source property on a non-UI thread (not on Dispatcher thread). In my application, I am using Rx (Reactive Extension) Scheduler, thus, I plan to provide one Rx scheduler for the execution.

例如,如果我绑定以下对象的属性Value,并且UI使用绑定更新该属性,则我希望Value属性的设置器在我提供的Rx调度程序上执行.

As an example, if I bind the property Value of the following object and the UI updates the property using the binding, I want the setter of Value property to be executed on an Rx scheduler I provided.

public class A : VMBase {  // VMBase provides the plumbing of INotifyPropertyChanged
    private string _Value;
    public string Value {
        get { return _Value; }
        set { SetField(ref _Value, value, () => Value); }
    }
}

可以修改源属性的设置器,以将更新切换到另一个线程.

It is possible to modify the source property's setter to switch the update to another thread.

public class A : VMBase {  // VMBase provides the plumbing of INotifyPropertyChanged
    private string _Value;
    public string Value {
        get { return _Value; }
        set { GetScheduler().Schedule(() => SetField(ref _Value, value, () => Value)); }
    }
}

但是,在我看来,这是不切实际的,因为我需要请用户修改其代码.

However, in my case this is not practical because I need to ask my users to modify their codes.

搜索该问题,发现可以按如下方式创建自定义WPF绑定:

Googling the issue, I found that I can create a custom WPF binding as follows: http://www.hardcodet.net/2008/04/wpf-custom-binding-class. However, I couldn't find where I should hook the code to invoke the update on the Rx scheduler.

任何解决方案或提示?我也对基于Reactive Extensions或Reactive UI的解决方案开放.

Any solutions or hint ? I am also opened to solutions based on Reactive Extensions or Reactive UI.

谢谢.

推荐答案

它可以带来更多的工作,但是您可以使用交互将ViewModel中的Commands链接到控件上的Events.这应该允许您拦截导致ViewModel上的值更新的事件,并使用您喜欢的任何方法来设置Value属性.在这里,我还使用了MVVM Light框架的"EventToCommand",但是如果您使用的是其他代码,则可以交换< i:InvokeCommandAction ... .

It can introduce quite a bit more work, but you can use interactions to link Commands in your ViewModel to Events on your controls. This should allow you to intercept the event causing the value update on your ViewModel and set your Value property using whatever method you like. Here I've also used the MVVM Light framework's 'EventToCommand', but you can swap in <i:InvokeCommandAction... if you're using something else.

<UserControl 
...other namespaces, declarations, etc...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">

    <Grid>
        <Button>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cmdextras:EventToCommand Command="{Binding Path=SomethingWentClickCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>

</UserControl>

重新配置它以适合您正在使用的任何控件/事件,然后您的codebehind/viewmodel类需要一个名为SomethingWentClickCommand的RelayCommand来检索新值并相应地更新绑定属性.

Reconfigure this to suit whatever control/event you're using, then your codebehind/viewmodel class needs a RelayCommand called SomethingWentClickCommand to retrieve the new value and update your binding property accordingly.

这篇关于在双向数据绑定中在非UI线程上调用源属性更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆