确保在MVVM WPF应用程序中的UI线程上调用OnPropertyChanged()
在我使用MVVM模式编写的WPF应用程序中,我有一个后台进程来完成这件事,但需要从UI中获取状态更新。
我使用MVVM模式,所以我的ViewModel几乎不知道向用户展示模型的视图(UI)。
假设我在ViewModel中有以下方法:
public void backgroundWorker_ReportProgress(object sender, ReportProgressArgs e)
{
this.Messages.Add(e.Message);
OnPropertyChanged("Messages");
}
在我看来,我有一个ListBox绑定到ViewModel的Messages属性( List<string>
)。 OnPropertyChanged
通过调用PropertyChangedEventHandler
来实现INotifyPropertyChanged
接口的角色。
我需要确保在UI线程上调用OnPropertyChanged
- 我该如何做到这一点? 我试过以下内容:
public Dispatcher Dispatcher { get; set; }
public MyViewModel()
{
this.Dispatcher = Dispatcher.CurrentDispatcher;
}
然后将以下内容添加到OnPropertyChanged
方法中:
if (this.Dispatcher != Dispatcher.CurrentDispatcher)
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(delegate
{
OnPropertyChanged(propertyName);
}));
return;
}
但这不起作用。 有任何想法吗?
WPF自动将属性更改编组到UI线程。 但是,它不编组收集更改,所以我怀疑您添加一条消息导致失败。
您可以自己手动编辑添加(请参阅下面的示例),或者使用类似于我以前写博客的技术。
手动编组:
public void backgroundWorker_ReportProgress(object sender, ReportProgressArgs e)
{
Dispatcher.Invoke(new Action<string>(AddMessage), e.Message);
OnPropertyChanged("Messages");
}
private void AddMessage(string message)
{
Dispatcher.VerifyAccess();
Messages.Add(message);
}
我真的很喜欢杰里米的回答:在Silverlight中调度
概要:
在ViewModel中放置分派器似乎不够高雅
创建一个Action <Action>属性,将其设置为仅在VM构造函数中运行该操作
本周我也有类似的情况(这里也是MVVM)。 我有一个单独的类来完成它的事情,报告事件处理程序的状态。 事件处理程序正在按预期方式调用,并且我可以看到使用Debug.WriteLine正确返回的结果。
但是对于WPF,不管我做了什么,UI都不会更新,直到过程完成。 该过程完成后,UI将按预期进行更新。 就好像它正在获取PropertyChanged一样,但是在一次完成UI更新之前等待线程完成。
(很让我沮丧的是,Windows.Forms中的代码与DoEvents和.Refresh()的工作方式类似。)
到目前为止,我通过在自己的线程上启动进程来解决这个问题:
//hook up event handler
myProcess.MyEvent += new EventHandler<MyEventArgs>(MyEventHandler);
//start it on a thread ...
ThreadStart threadStart = new ThreadStart(myProcess.Start);
Thread thread = new Thread(threadStart);
thread.Start();
然后在事件处理程序中:
private void MyEventHandler(object sender, MyEventArgs e) {
....
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Send,
(DispatcherOperationCallback)(arg =>
{
//do UI updating here ...
}), null);
我不推荐这段代码,因为我仍然试图理解WPF线程模型,Dispatcher是如何工作的,以及为什么在我的情况下,即使事件处理程序按预期方式调用,过程完成之前UI也不会更新通过设计?)。 但到目前为止,这对我来说已经奏效。
我发现这两个链接很有用:
http://www.nbdtech.com/blog/archive/2007/08/01/Passing-Wpf-Objects-Between-Threads-With-Source-Code.aspx
http://srtsolutions.com/blogs/mikewoelmer/archive/2009/04/17/dealing-with-unhandled-exceptions-in-wpf.aspx
链接地址: http://www.djcxy.com/p/56207.html上一篇: Making sure OnPropertyChanged() is called on UI thread in MVVM WPF app
下一篇: WPF: Why does CommandBindings only use RoutedCommand which breaks MVVM?