从父抚养事件更新子视图模型

时间:2013-12-03 10:12:17

标签: c# wpf events mvvm backgroundworker

涉及的课程:

  1. 经典MVVM作为儿童控件的容器。
  2. 使用自己的视图模型控制子项(按钮具体)。
  3. BackgroundWorker通过套接字远程主机进行轮询。
  4. 行为:

    • 主应用程序从XML列表开始加载子控件。 每个Child都拥有父视图中更新事件的处理程序 模型(我们称之为主视图模型)更新了属性 子。
    • 主ViewModel启动BackgroundWorker
    • BackgroundWorker调用Socket方法并使用ViewModel Callback进行响应。
    • Callback更新Main ViewModel属性。

    因为它在这里完美无缺,但随后:

    • 更新后的属性会在集合中引发事件,子处理程序将以自己的属性更新开始。
    • 在引发更新异常时:
      

    调用线程无法访问此对象,因为它不同   线程拥有它。

    几秒钟后按钮会更新。我猜是因为UI线程再次获取控件并更新控件。但是,有更好的方法来解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

只有拥有线程才能更新窗口元素(即控件)。

使用Control.Invoke()方法更改按钮。我有一个小助手班,我写的是为了解决这个问题。

public static class ControlEx
{
    public static void DoSafely(this Control control, Action action)
    {
        if (control.InvokeRequired)
            control.Invoke(new Action(() =>
                {
                    action();
                    Application.DoEvents();
                }));
        else
            action();
    }
}

所以不要做类似的事情:

button.Text = "new text";

来自另一个帖子,我现在打电话给

button.DoSafely(() => button.Text = "new text");

答案 1 :(得分:1)

要扩展Uebercoder的答案,您可能不关心视图模型中的控件,但仍需要将后台更新编组到主线程上。

因此,无论是在后台工作者中,还是在主视图模型中,您都需要执行以下操作:

Application.Current.Dispatcher.BeginInvoke((Action)(() => { /* update properties */ } )));
相关问题