{"id":402,"date":"2015-01-20T15:26:44","date_gmt":"2015-01-20T14:26:44","guid":{"rendered":"http:\/\/dev.flauschig.ch\/wordpress\/?p=402"},"modified":"2015-01-20T15:26:44","modified_gmt":"2015-01-20T14:26:44","slug":"notify-viewmodel-property-when-a-property-in-the-model-changes","status":"publish","type":"post","link":"http:\/\/dev.flauschig.ch\/wordpress\/?p=402","title":{"rendered":"Notify ViewModel property when a property in the model changes"},"content":{"rendered":"<p>Trying to be MVVM compliant is not always easy.<\/p>\n<p>Take the following scenario:<\/p>\n<p>There is a model with a property &#8220;Status&#8221;. This property changes values according to some logic in the model. This property should now be presented in the view. To have correct MVVM, the ViewModel has also a property &#8220;Status&#8221;, which is bound to the view.<br \/>\nSo, now how can the model inform the viewmodel when the &#8220;Status&#8221; of the model changed?<\/p>\n<p>The best bet is to have a StatusChanged event on the model and let the viewmodel subscribe to it and fire the viewmodel&#8217;s own propertychanged for it&#8217;s &#8220;Status&#8221; property. This can get quite tedious so I created a small helper: PropertyChangedProxy<\/p>\n<p>For this, the model and the viewmodel need to implement INotifyPropertyChanged. Then on the viewmodel, you can create new a new instance of the PropertyChangedProxy for each property of the model where you want the viewmodel to be notified, in a typesafe way.<\/p>\n<p>Such an instance would look like this:<\/p>\n<pre class=\"lang:default decode:true \" >var statusPropertyChangedProxy = new PropertyChangedProxy&lt;MainModel, StatusType&gt;(\r\n\t_model, m =&gt; m.Status,\r\n\tnewValue =&gt; OnPropertyChanged(\"Status\"));<\/pre>\n<p>So as you see, you just need to give the source (which is the model), the property of the source (as a nice expression) and an action, that should be called when the source&#8217;s property changes (which in this case is just to fire a OnPropertyChanged on the ViewModel itself).<\/p>\n<p>Here&#8217;s a complete small example of a model and viewmodel, where the viewmodel is automatically notified when the model&#8217;s &#8220;Status&#8221; changes so that the viewmodel can forward this to the view:<\/p>\n<pre class=\"lang:default decode:true \" >public class MyModel : INotifyPropertyChanged\r\n{\r\n\tprivate string _status;\r\n\tpublic string Status\r\n\t{\r\n\t\tget { return _status; }\r\n\t\tset { _status = value; OnPropertyChanged(); }\r\n\t}\r\n\r\n\t\/\/ Default INotifyPropertyChanged\r\n\tpublic event PropertyChangedEventHandler PropertyChanged;\r\n\tprotected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)\r\n\t{\r\n\t\tvar handler = PropertyChanged;\r\n\t\tif (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));\r\n\t}\r\n}\r\n\r\npublic class MyViewModel : INotifyPropertyChanged\r\n{\r\n\tpublic string Status\r\n\t{\r\n\t\tget { return _model.Status; }\r\n\t}\r\n\r\n\tprivate PropertyChangedProxy&lt;MyModel, string&gt; _statusPropertyChangedProxy;\r\n\tprivate MyModel _model;\r\n\tpublic MyViewModel(MyModel model)\r\n\t{\r\n\t\t_model = model;\r\n\t\t_statusPropertyChangedProxy = new PropertyChangedProxy&lt;MyModel, string&gt;(\r\n\t\t\t_model, myModel =&gt; myModel.Status, s =&gt; OnPropertyChanged(\"Status\")\r\n\t\t);\r\n\t}\r\n\r\n\t\/\/ Default INotifyPropertyChanged\r\n\tpublic event PropertyChangedEventHandler PropertyChanged;\r\n\tprotected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)\r\n\t{\r\n\t\tvar handler = PropertyChanged;\r\n\t\tif (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));\r\n\t}\r\n}<\/pre>\n<p>Here&#8217;s the source of the PropertyChangedProxy:<\/p>\n<pre class=\"lang:default decode:true \" title=\"PropertyChangedProxy\" >\/\/\/ &lt;summary&gt;\r\n\/\/\/ Proxy class to easily take actions when a specific property in the \"source\" changed\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ Last updated: 20.01.2015\r\n\/\/\/ &lt;typeparam name=\"TSource\"&gt;Type of the source&lt;\/typeparam&gt;\r\n\/\/\/ &lt;typeparam name=\"TPropType\"&gt;Type of the property&lt;\/typeparam&gt;\r\npublic class PropertyChangedProxy&lt;TSource, TPropType&gt; where TSource : INotifyPropertyChanged\r\n{\r\n\tprivate readonly Func&lt;TSource, TPropType&gt; _getValueFunc;\r\n\tprivate readonly TSource _source;\r\n\tprivate readonly Action&lt;TPropType&gt; _onPropertyChanged;\r\n\tprivate readonly string _modelPropertyname;\r\n\r\n\t\/\/\/ &lt;summary&gt;\r\n\t\/\/\/ Constructor for a property changed proxy\r\n\t\/\/\/ &lt;\/summary&gt;\r\n\t\/\/\/ &lt;param name=\"source\"&gt;The source object to listen for property changes&lt;\/param&gt;\r\n\t\/\/\/ &lt;param name=\"selectorExpression\"&gt;Expression to the property of the source&lt;\/param&gt;\r\n\t\/\/\/ &lt;param name=\"onPropertyChanged\"&gt;Action to take when a property changed was fired&lt;\/param&gt;\r\n\tpublic PropertyChangedProxy(TSource source, Expression&lt;Func&lt;TSource, TPropType&gt;&gt; selectorExpression, Action&lt;TPropType&gt; onPropertyChanged)\r\n\t{\r\n\t\t_source = source;\r\n\t\t_onPropertyChanged = onPropertyChanged;\r\n\t\t\/\/ Property \"getter\" to get the value\r\n\t\t_getValueFunc = selectorExpression.Compile();\r\n\t\t\/\/ Name of the property\r\n\t\tvar body = (MemberExpression)selectorExpression.Body;\r\n\t\t_modelPropertyname = body.Member.Name;\r\n\t\t\/\/ Changed event\r\n\t\t_source.PropertyChanged += SourcePropertyChanged;\r\n\t}\r\n\r\n\tprivate void SourcePropertyChanged(object sender, PropertyChangedEventArgs e)\r\n\t{\r\n\t\tif (e.PropertyName == _modelPropertyname)\r\n\t\t{\r\n\t\t\t_onPropertyChanged(_getValueFunc(_source));\r\n\t\t}\r\n\t}\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Trying to be MVVM compliant is not always easy. Take the following scenario: There is a model with a property &#8220;Status&#8221;. This property changes values according to some logic in the model. This property should now be presented in the view. To have correct MVVM, the ViewModel has also a property &#8220;Status&#8221;, which is bound &hellip; <\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[4,3],"tags":[],"class_list":{"0":"entry","1":"post","2":"publish","3":"author-roemer","4":"post-402","6":"format-standard","7":"category-csharp","8":"category-programming"},"acf":[],"views":5273,"_links":{"self":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/402"}],"collection":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=402"}],"version-history":[{"count":0,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/402\/revisions"}],"wp:attachment":[{"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=402"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/dev.flauschig.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}