Code Smarter Not Harder #3: #CodeRush Property Setter Template for #CaliburnMicro

In our third installment, we will look at the latest version of CodeRush and how we can implement a custom template for Caliburn.Micro that takes care of a custom property setter for us. Now in the latest version of CodeRush there is already a template created fro MVVM implementations that creates a setter routine for a property complete with the wire-up for the INotify call. However, if you are working with a base viewmodel class like the IScreen implementation of Caliburn.Micro then this kind of gets in the way…because we already have a nice lambda expression based call for NotifyOfPropertyChange.

So in our basic setup when we would type pb <spacebar> to create our property stub, we would end up with this…

image

Now this is okay if the form is pretty simple and I have to retype the PropertyChanged call but if I am working on a complex set of windows/screens this just gets downright annoying. So what we want to do is to create a custom CodeRush template that will enact the proper call to NotifyOfProperyChange but not interfere if we happen to be using a project that is not using Caliburn.Micro. Luckily, Caliburn.Micro uses IScreen as its base for the screens and windows so all we have to do is to check if the current class we are in inherits from IScreen.

So first off, we need to open the CodeRush options screen by going to DevExpress –> Options… in the top toolbar in Visual Studio.

image

Now you’ll want to dig down into the proper section in the list of folders…which is a little tricky if this is your first time editing templates. So go to Editor –> Selections –> Templates.  Don’t get overwhelmed with the number of templates. We are looking for a specific one. So go ahead and type #PropertySetter# into the Search box to have it take you straight-away to the one we will be modifying.

image

You’ll notice that there are already two expansion templates that are used. If you click each one of them and look at the expansion window on the right you will be able to see that one is a basic implementation and then the InheritsFrom one is the more complex one that is used when the class inherits from INotify. This INotify one will be the one that we use as our baseline.

Click on the red plus sign that is above the Expansion window on the right hand side. This will create a new expansion template for you.

image

Initially the expansion will be blank. In the Expansion text area on the right hand side, type in the following. You can copy and paste from the current InheritsFrom template as your starting point.

{
if(«:#FieldQualifier#»«:#PropertyVar#» == value)
return;
«:#FieldQualifier#»«:#PropertyVar#» = value;
NotifyOfPropertyChange(()=>;«:#PropertyVar#»);
}

Here all we have done is take the original expansion that we were copying from and replaced the PropertyChanged call with out custom call. Now we need to tie it into being fired when our class inherits from IScreen. So in the Use area that is directly below the Expansion textblock area we want to navigate down the treeview to Code –> InheritsFrom. Check the checkbox to activate it then right click on it and select Parameters.

image

In the Parameters window simply type in Caliburn.Micro.IScreen and click OK.

image

Now there is one last very important thing that you must do. The ordering of our #PropertySetter# expansions in the treeview on the left is the order in which they will be fired. If you leave things as is.. then the INotify version will fire off first and your custom one will not get called because IScreen implements INotify. So now you want to affect the order by selected your custom expansion and clicking on the blue up arrow that is directly above the Expansion textblock on the right. Do this until you expansion is the first one in the list. Click Apply when finished to have all your changes applied.

image

Now give it a whirl and you should see the proper expansion as shown below.

image

 

Hopefully, this little technique will help you save a lot of keystrokes because it will work basically with any base class that you would be using within your MVVM implementation.

 

Cheers!
AJ