Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it considered bad practice to have ViewModel objects hold the Dispatcher?

My WPF application is structured using the MVVM pattern. The ViewModels will communicate asynchronously with a server, and when the requested data is returned a callback in the ViewModel is triggered, and it will do something with this data. This will run on a thread which is not the UI Thread. Sometimes these callbacks involve work that needs to be done on the UI thread, so I need the Dispatcher. This might be things such as:

  • Adding data to an ObservableCollection
  • Trigger Prism commands that will set something to be displayed in the GUI
  • Creating WPF objects of some kind.

I try to avoid the latter, but the two first points here I find to be reasonable things for ViewModels to do. So; is it okay to have ViewModels hold the Dispatcher to be able to Invoke commands for the UI thread? Or is this considered bad practice? And why?

like image 949
stiank81 Avatar asked Mar 12 '10 11:03

stiank81


3 Answers

Since an ObservableCollection must be updated on the thread it belongs to (assuming a GUI app), and ObservableCollections should be part of the ViewModel, then there's a clear case for the ViewModel having a Dispatcher.

I can't see it being part of the Model.

like image 90
kyoryu Avatar answered Nov 09 '22 11:11

kyoryu


Ideally, a ViewModel should be totally independent from the UI technology used. We should theoretically be able to reuse it for Windows Forms (if we pimp up the Windows Forms controls a little bit to support better binding), for Web pages (I envision some kind of fancy mechanism here that would compile the ViewModel also into Javascript), and for any future technologies. Not all of these technologies will use the Dispatcher model.

That said, i consider it as a pragmatic compromise to include the Dispatcher in the ViewModel nowadays. In my ViewModel base class, I check for the current Dispatcher:

    protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (Deployment.Current.Dispatcher == null || Deployment.Current.Dispatcher.CheckAccess())
        {
            base.OnPropertyChanged(sender, e);
        }
        else
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => base.OnPropertyChanged(sender, e));
        }
    }

I still have the dependency on System.Windows of course, but oh well. :->

like image 29
herzmeister Avatar answered Nov 09 '22 11:11

herzmeister


I agree with kyoryu and I would like to note that it only creates a dependency on the ServiceModel lobrary (which you already have) and not on the View itself, so there is very little to object against this construction.

I was trying out a few things with WPF, a simple VM and threads yesterday and came to the conclusion that I absolutely needed to pass the Dispatcher to the VM.

Also see Using WPF UI thread should always ensure STA apartment mode, right?

like image 1
Henk Holterman Avatar answered Nov 09 '22 12:11

Henk Holterman