{"id":33,"date":"2010-03-31T20:27:00","date_gmt":"2010-03-31T20:27:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/davidrickard\/2010\/03\/31\/using-the-dispatcher-with-mvvm\/"},"modified":"2010-03-31T20:27:00","modified_gmt":"2010-03-31T20:27:00","slug":"using-the-dispatcher-with-mvvm","status":"publish","type":"post","link":"https:\/\/engy.us\/blog\/2010\/03\/31\/using-the-dispatcher-with-mvvm\/","title":{"rendered":"Using the Dispatcher with MVVM"},"content":{"rendered":"<p>When writing an MVVM application, you want to separate from the UI. However you also need to make sure that UI updates happen on the UI thread. Changes made through INotifyPropertyChanged get automatically marshaled to the UI thread, so in most cases you&rsquo;ll be fine. However, when using INotifyCollectionChanged (such as with an ObservableCollection), these changes are <em>not<\/em> marshaled to the UI thread.<\/p>\n<p>This means that unless you modify your collection on the UI thread, you&rsquo;ll get a cross threading error. Thus the problem. We&rsquo;re in the ViewModel and we don&rsquo;t have access to the Dispatcher. That&rsquo;s on a View object. How do we update the collection on the UI thread?<\/p>\n<p>I came up with a small static class to help with this:<\/p>\n<pre class=\"code\"><span style=\"color: blue;\"><\/span><\/pre>\n<pre><span style=\"color: blue;\">public<\/span> <span style=\"color: blue;\">static<\/span> <span style=\"color: blue;\">class<\/span> <span style=\"color: #2b91af;\">DispatchService<\/span>\n{\n    <span style=\"color: blue;\">public<\/span> <span style=\"color: blue;\">static<\/span> <span style=\"color: blue;\">void<\/span> Invoke(<span style=\"color: #2b91af;\">Action<\/span> action)\n    {\n        <span style=\"color: #2b91af;\">Dispatcher<\/span> dispatchObject = <span style=\"color: #2b91af;\">Application<\/span>.Current.Dispatcher;\n        <span style=\"color: blue;\">if<\/span> (dispatchObject == <span style=\"color: blue;\">null<\/span> || dispatchObject.CheckAccess())\n\t{\n            action();\n        }\n        <span style=\"color: blue;\">else<\/span>\n        {\n            dispatchObject.Invoke(action);\n        }\n    }\n}<\/pre>\n<p>When your ViewModel gives the DispatchService actions, it can run them on the correct thread. Which is, in the case of unit tests, always the current thread. A call to the DispatchService may look like this:<\/p>\n<pre class=\"code\"><span style=\"color: #2b91af;\">DispatchService<\/span>.Invoke(() =&gt;\n{\n    <span style=\"color: blue;\">this<\/span>.MyCollection.Add(<span style=\"color: #a31515;\">\"new value\"<\/span>);\n});<\/pre>\n<p>The use of a simple lambda statement makes it a relatively lightweight way of updating on the correct thread.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When writing an MVVM application, you want to separate from the UI. However you also need to make sure that UI updates happen on the UI thread. Changes made through INotifyPropertyChanged get automatically marshaled to the UI thread, so in most cases you&rsquo;ll be fine. However, when using INotifyCollectionChanged (such as with an ObservableCollection), these &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/engy.us\/blog\/2010\/03\/31\/using-the-dispatcher-with-mvvm\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Using the Dispatcher with MVVM&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[1],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pahBcK-x","jetpack-related-posts":[{"id":79,"url":"https:\/\/engy.us\/blog\/2018\/10\/03\/wpf-databinding-using-dynamicdata\/","url_meta":{"origin":33,"position":0},"title":"WPF Databinding using DynamicData","date":"October 3, 2018","format":false,"excerpt":"My project is MVVM and I had been using ReactiveList<T> as my go-to observable collection for viewmodel properties. But ReactiveUI deprecated ReactiveList in 8.6.1. So I needed to get on to the new recommended library: DynamicData. But there is no direct drop-in replacement you can do like ObservableCollection<T> <-> ReactiveList<T>.\u2026","rel":"","context":"With 2 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":120,"url":"https:\/\/engy.us\/blog\/2020\/01\/01\/implementing-a-custom-window-title-bar-in-wpf\/","url_meta":{"origin":33,"position":1},"title":"Implementing a Custom Window Title Bar in WPF","date":"January 1, 2020","format":false,"excerpt":"There are several good reasons for wanting custom window chrome in WPF, such as fitting in additional UI or implementing a Dark theme. However the actual implementation is kind of tricky, since it is now your job to provide a bunch of features that you used to get for free.\u2026","rel":"","context":"With 12 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":88,"url":"https:\/\/engy.us\/blog\/2018\/10\/20\/dark-theme-in-wpf\/","url_meta":{"origin":33,"position":2},"title":"Dark Theme in WPF","date":"October 20, 2018","format":false,"excerpt":"In a recent Windows 10 update a toggle switch was added to allow the user to specify that they wanted \"Dark\" themes in apps: I decided to add support for this to VidCoder. But no updates to WPF were made to make this easy. WPF does having theming support where\u2026","rel":"","context":"With 5 comments","img":{"alt_text":"","src":"https:\/\/i2.wp.com\/engy.us\/blog\/wp-content\/uploads\/2018\/10\/VidCoderDarkExample.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":43,"url":"https:\/\/engy.us\/blog\/2010\/03\/08\/saving-window-size-and-location-in-wpf-and-winforms\/","url_meta":{"origin":33,"position":3},"title":"Saving window size and location in WPF and WinForms","date":"March 8, 2010","format":false,"excerpt":"A common user interface tweak is to save the size and location of a window and restore that state when the program starts up again. That way, the users don\u2019t need to re-do their work of resizing and moving the windows to where they want them. However I\u2019ve found that\u2026","rel":"","context":"With 21 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":51,"url":"https:\/\/engy.us\/blog\/2015\/07\/17\/installing-net-framework-4-5-automatically-with-inno-setup\/","url_meta":{"origin":33,"position":4},"title":"Installing .NET Framework 4.7 automatically with Inno Setup","date":"July 17, 2015","format":false,"excerpt":"In this guide I will walk through how to get the .NET framework to download and install on-the-fly in an Inno Setup installer. It works in 3 steps: Detect if the desired .NET framework is installed Download the .NET Framework bootstrap installer with Inno Download Plugin Run the bootstrap installer\u2026","rel":"","context":"In \".net framework 4.5 inno setup\"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/engy.us\/blog\/wp-content\/uploads\/2015\/07\/7028.InstallingFramework2-1.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":146,"url":"https:\/\/engy.us\/blog\/2021\/02\/28\/installing-net-5-runtime-automatically-with-inno-setup\/","url_meta":{"origin":33,"position":5},"title":"Installing .NET 5 Runtime Automatically with Inno Setup","date":"February 28, 2021","format":false,"excerpt":"In this guide I will walk through how to get the .NET 5 runtime to download and install on-the-fly in an Inno Setup installer. It works in 3 steps: Detect if the desired .NET runtime is installedDownload the .NET Runtime bootstrap installer with Inno Download PluginRun the bootstrap installer in\u2026","rel":"","context":"With 2 comments","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/engy.us\/blog\/wp-content\/uploads\/2021\/02\/image.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/posts\/33"}],"collection":[{"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/comments?post=33"}],"version-history":[{"count":0,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/posts\/33\/revisions"}],"wp:attachment":[{"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/media?parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/categories?post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/tags?post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}