{"id":79,"date":"2018-10-03T06:56:11","date_gmt":"2018-10-03T06:56:11","guid":{"rendered":"https:\/\/engy.us\/blog\/?p=79"},"modified":"2018-10-03T06:56:11","modified_gmt":"2018-10-03T06:56:11","slug":"wpf-databinding-using-dynamicdata","status":"publish","type":"post","link":"https:\/\/engy.us\/blog\/2018\/10\/03\/wpf-databinding-using-dynamicdata\/","title":{"rendered":"WPF Databinding using DynamicData"},"content":{"rendered":"<p>My project is MVVM and I had been using ReactiveList&lt;T&gt; as my go-to observable collection for viewmodel properties. But ReactiveUI <a href=\"https:\/\/reactiveui.net\/blog\/2018\/08\/deprecated-reactive-list\">deprecated ReactiveList in 8.6.1<\/a>. So I needed to get on to the new recommended library: <a href=\"https:\/\/github.com\/RolandPheasant\/DynamicData\">DynamicData<\/a>.<\/p>\n<p>But there is no direct drop-in replacement you can do like ObservableCollection&lt;T&gt; &lt;-&gt; ReactiveList&lt;T&gt;. I grabbed the NuGet package, dropped in SourceList&lt;T&gt;, but that doesn&#8217;t work. SourceList&lt;T&gt; does not implement INotifyCollectionChanged, which is what WPF looks for when binding to ListView, GridView, ItemsControl, etc. So how do we bind to this thing? After some fruitless searches I dug through the source code unit tests and found the answer. Add this to the viewmodel class:<\/p>\n<pre>private readonly SourceList&lt;string&gt; myList = new SourceList&lt;string&gt;();\r\npublic IObservableCollection&lt;string&gt; MyListBindable { get; } = new ObservableCollectionExtended&lt;string&gt;();\r\n<\/pre>\n<p>And this to its constructor:<\/p>\n<pre>this.myList.Connect().Bind(this.MyListBindable).Subscribe();\r\n<\/pre>\n<p>It&#8217;s a two-stage affair. The SourceList&lt;T&gt; is where all the operations happen. Adds, clears, deletes and all that. But you don&#8217;t directly observe the source list. To do that, you need to call Connect() to get an IObservable&lt;IChangeSet&lt;T&gt;&gt; . If you follow this observable you can see everything that&#8217;s changed about the collection by looking at the change sets.<\/p>\n<p>But you still need to do one more thing: get it in a format that the WPF UI can bind to, that is an object that implements INotifyCollectionChanged. ObservableCollectionExtended is DynamicData&#8217;s implementation of that. The Bind() call &#8220;slaves&#8221; it to the SourceList. Any changes made in the SourceList are now reflected in the ObservableCollectionExtended. A final call to Subscribe() activates it. Now since we&#8217;re exposing it as a property, we can bind our UI to it:<\/p>\n<pre>&lt;ItemsControl\r\n\tItemsSource=\"{Binding MyListBindable}\"\r\n\t...\r\n<\/pre>\n<p>The important thing here is to remember that this property is here ONLY so the UI can bind to it. That&#8217;s why I&#8217;ve named it Bindable: so I&#8217;ll realize I&#8217;m doing something wrong if I try to modify it directly.<\/p>\n<p>The ObservableCollectionExtended property also allows you to get batches to avoid update churn from making individual edits to the collection. When you call Edit() on the SourceList&lt;T&gt;:<\/p>\n<pre>this.myList.Edit(innerList =&gt;\r\n{\r\n\tinnerList.Clear();\r\n\tforeach (string name in names)\r\n\t{\r\n\t\tinnerList.Add(name);\r\n\t}\r\n});\r\n<\/pre>\n<p>It will batch up all the changes made into one event under INotifyCollectionChanged, meaning the UI only needs to react once.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My project is MVVM and I had been using ReactiveList&lt;T&gt; 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&lt;T&gt; &lt;-&gt; ReactiveList&lt;T&gt;. I grabbed the NuGet package, &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/engy.us\/blog\/2018\/10\/03\/wpf-databinding-using-dynamicdata\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;WPF Databinding using DynamicData&#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-1h","jetpack-related-posts":[{"id":43,"url":"https:\/\/engy.us\/blog\/2010\/03\/08\/saving-window-size-and-location-in-wpf-and-winforms\/","url_meta":{"origin":79,"position":0},"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":33,"url":"https:\/\/engy.us\/blog\/2010\/03\/31\/using-the-dispatcher-with-mvvm\/","url_meta":{"origin":79,"position":1},"title":"Using the Dispatcher with MVVM","date":"March 31, 2010","format":false,"excerpt":"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\u2019ll be fine. However, when using INotifyCollectionChanged (such\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":79,"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":120,"url":"https:\/\/engy.us\/blog\/2020\/01\/01\/implementing-a-custom-window-title-bar-in-wpf\/","url_meta":{"origin":79,"position":3},"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":82,"url":"https:\/\/engy.us\/blog\/2018\/10\/04\/item-change-tracking-in-dynamicdata\/","url_meta":{"origin":79,"position":4},"title":"Item change tracking in DynamicData","date":"October 4, 2018","format":false,"excerpt":"Since ReactiveUI's ReactiveList<T> has recently been deprecated, I've been moving to DynamicData. One feature I used from ReactiveList was item change tracking. It might look something like this: var myList = new ReactiveList<MyClass>(); myList.ChangeTrackingEnabled = true; myList.ItemChanged .Where(x => x.PropertyName == nameof(MyClass.SomeProperty)) .Select(x => x.Sender) .Subscribe(myObject => { \/\/ Do\u2026","rel":"","context":"With 5 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":146,"url":"https:\/\/engy.us\/blog\/2021\/02\/28\/installing-net-5-runtime-automatically-with-inno-setup\/","url_meta":{"origin":79,"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\/79"}],"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=79"}],"version-history":[{"count":2,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/posts\/79\/revisions"}],"predecessor-version":[{"id":81,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/posts\/79\/revisions\/81"}],"wp:attachment":[{"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/media?parent=79"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/categories?post=79"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/engy.us\/blog\/wp-json\/wp\/v2\/tags?post=79"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}