If you have worked with MVVM and/or data-binding before, there is a good chance that you are very familiar with the INotifyPropertyChanged interface. With this interface you can invoke an event whenever a value of a property has changed. The view notices this change, because of this event and updates the UI accordingly.
While this is a great mechanism, it isn’t really great in terms of don’t repeating yourself. The code is always 95 percent the same and you have to implement it in each ViewModel (or PageModel). You could abstract it to a base class, but still you would have to that for each project.
The brilliant minds behind PropertyChanged.Fody must have thought the same thing and came up with a solution for this. Instead of implementing the interface yourself, you can now adorn your classes and properties with attributes, that will inject the needed code at compile time, awesome! This way we Don’t Repeat Yourselves and can focus on what really matters.
UPDATE! Please note: Do not use the ImplementPropertyChanged attribute anymore. You should just implement the INotifyPropertyChanged interface on a class and Fody will be injected there. If you do not want to implement the INotifyPropertyChanged interface yourself, you can now use the AddINotifyPropertyChangedInterfaceAttribute supplied by the Fody library.
Implementing PropertyChanged.Fody #
Let’s see what that looks like for us in code.
First I will setup an Xamarin.Forms app with the INotifyPropertyChanged method. It will have one Page and one PageModel. For the sake of length I will not use a MVVM framework but instead just bind the PageModel myself and use plain-old events. In real-life; don’t try this at home! Also my naming conventions could be better.. A lot.
My page looks like this:
A label and two buttons. The label has a binding to a property called SampleText. With the first button I will change the text and thus causing the INotifyPropertyChanged to get invoked. The second button we will use later to navigate to another page.
More interesting is the code-behind for this, or rather: the PageModel.
Notice how there is a property with a backing field, a public event for the PropertyChangedEventHandler and a OnPropertyChanged method. Actually only the PropertyChangedEventHandler is mandatory when implementing the INotifyPropertyChanged interface.
When the SampleText property gets set, first the value is changed in the backing field and then our OnPropertyChanged method is fired which in its turn notifies anyone who wants to listen - in this case the Page - and then the listener can act as they see fit. When running this, the result should look like underneath.
If we look back at the code an count the lines that have to do with the code to notify about a value change of one property, you can come up with a number somewhere around 10-15 lines depending on how you count what. If there were more properties, and there can be a number if you are using stuff like MVVM, there will be a lot of extra code that seems redundant.
Enter PropertyChanged.Fody. Simply install the NuGet package on your PCL project, and that is basically it.
Doing this from Visual Studio on Windows will automatically update the FodyWeavers.xml file that is added to your project. With this file you weave the different Fody plugins into your project. On Xamarin Studio the file gets added to your project, but you will need to add the PropertyChanged entry to it yourself. It isn’t hard! Just open the FodyWeavers.xml file and add into the Weavers node. The resulting file should look like this.
If you use more plugins from the Fody suite, you should add them here as well.
Now I have created almost a copy of the Page which now just has a label and button.
But again, the PageModel is much more interesting.
And that is it! Wow! Just the property and that is all, and basically; that is all we want anyway. After wiring up the events to go to the next page and change the text, the result is this:
Using attributes #
The magic happens with the [ImplementPropertyChanged] attribute (UPDATE: See above). With this you mark this class to be injected with the Fody code and thus have the INotifyPropertyChanged code at compile-time. If you just let this sink in for a moment, you will probably go from ‘WOW! I didn’t know I needed this, but I want it!’ to ‘But what about properties that do not need the PropertyChanged functionality, won’t it be a performance hit?’. A performance hit would be an overstatement, but of course, it will be implemented for each property, whereas you have some more fine-grained control over the invocation with implementing the interface.
That is why they have come up with a couple of more attributes! To exclude a property from injecting the code you can use the [DoNotNotify] attribute on the property.
There are a couple of more you can use, I suggest you read up on it on their GitHub page about it. There you can also see the code that is generated at compile-time. One that I want to mention is the [AlsoNotifyFor(nameof(PropertyName))], this is one I use a lot as well. With this you can let the PropertyChanged event also fire for another property. So, when the value of PropertyA is changed, and you have put the [AlsoNotifyFor(nameof(PropertyB))] attribute above it, the event is raised for that one as well. This causes the UI to update the viewing of PropertyB as well.
The source-code for this sample can be found here: https://github.com/jfversluis/propertychangedfodysample
Note that PropertyChanged is part of the Fody suite which has a lot more of nifty NuGets for you to use, and they are not only for Xamarin either!