Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
612 views
in Technique[技术] by (71.8m points)

.net - Making sure OnPropertyChanged() is called on UI thread in MVVM WPF app

In a WPF app that I'm writing using the MVVM pattern, I have a background process that doing it's thing, but need to get status updates from it out to the UI.

I'm using the MVVM pattern, so my ViewModel knows virtually nothing of the view (UI) that is presenting the model to the user.

Say I have the following method in my ViewModel:

public void backgroundWorker_ReportProgress(object sender, ReportProgressArgs e)
{
    this.Messages.Add(e.Message);
    OnPropertyChanged("Messages");
}

In my view, I have a ListBox bound to the Messages property (a List<string>) of the ViewModel. OnPropertyChanged fulfills the role of the INotifyPropertyChanged interface by calling a PropertyChangedEventHandler.

I need to ensure that OnPropertyChanged is called on the UI thread - how do I do this? I've tried the following:

public Dispatcher Dispatcher { get; set; }
public MyViewModel()
{ 
    this.Dispatcher = Dispatcher.CurrentDispatcher;
}

Then adding the following to the OnPropertyChanged method:

if (this.Dispatcher != Dispatcher.CurrentDispatcher)
{
    this.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(delegate
    {
        OnPropertyChanged(propertyName);
    }));
    return;
}

but this did not work. Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

WPF automatically marshals property changes to the UI thread. However, it does not marshal collection changes, so I suspect your adding a message is causing the failure.

You can marshal the add manually yourself (see example below), or use something like this technique I blogged about a while back.

Manually marshalling:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...