Reducing MVVM Light Viewmodel Code with Fody Property Dependencies and Custom Property Changed Methods

In other previous articles I’ve written about Fody and this article we’ll see how we can use the PropertyChanged.Fody addin with MVVM Light viewmodels.

Windows Store app screenshot

The preceding screenshot shows the app in action: a name TextBox is twoway data-bound to the viewmodel, when a different name is typed, the TextBlock shows the uppercase version.

The user can also type a color into the color box and a bit of reflection happens to convert this string to a color from the Colors class.

Windows Store app screenshot with different bg color

The following code shows the (non Fody-fied) viewmodel:

More...

SHARE:

Say Goodbye to Boring INotifyPropertyChanged Implementation in Universal Windows Apps with Fody

We need to implement INotifyPropertyChanged to allow bindings to be updated. For example in a simple viewmodel to add 2 numbers:

namespace UniFodyDemo
{    
    internal class CalculatorViewModel : INotifyPropertyChanged
    {
        private ICommand _addCommand;
        private string _firstNumber;
        private string _secondNumber;

        public CalculatorViewModel()
        {
            FirstNumber = "5";
            SecondNumber = "10";
            Result = "";

            AddCommand = new RelayCommand(Add);
        }


        // Use strings to simplify demo code (so no val converter)
        public string FirstNumber
        {
            get { return _firstNumber; }
            set
            {
                _firstNumber = value;
                OnPropertyChanged();
            }
        }

        public string SecondNumber
        {
            get { return _secondNumber; }
            set
            {
                _secondNumber = value;
                OnPropertyChanged();
            }
        }

        public string Result { get; set; }

        public ICommand AddCommand
        {
            get { return _addCommand; }
            private set
            {
                _addCommand = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void Add(object obj)
        {
            var a = int.Parse(FirstNumber);
            var b = int.Parse(SecondNumber);

            Result = (a + b).ToString();
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

There’s more code here than we’d need if we didn’t have to implement INotifyPropertyChanged. Really the important things are the 3 properties that we bind to and the add command / method.

The XAML in both the Windows Store app and Windows Phone app looks like:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel Width="200">
        <TextBlock Text="{Binding FirstNumber, Mode=TwoWay}"></TextBlock>
        <TextBlock Text="{Binding SecondNumber, Mode=TwoWay}"></TextBlock>
        <Button Command="{Binding AddCommand}">Add</Button>
        <TextBlock Text="{Binding Result, Mode=TwoWay}"></TextBlock>
    </StackPanel>
</Grid>

Without implementing INotifyProperty changed, clicking the Add button won’t be of much use, we wont see the result.

The solution looks like the following, the shared project contains the viewmodel.

image

It would be great not have to write this same INotifyProperty stuff for everything we want to bind to/from. Using a NuGet package called PropertyChanged.Fody we can achieve this.

First this package needs to be installed into both the Windows Store and Windows Phone app projects. This is because the shared code in the viewmodel isn’t compiled in that shared project, rather the source code is compiled individually in both the Store/Phone projects.

Now the viewmodel can be simplified:

namespace UniFodyDemo
{
    [ImplementPropertyChanged]
    class CalculatorViewModel
    {
        public CalculatorViewModel()
        {
            FirstNumber = "5";
            SecondNumber = "10";
            Result = "";

            AddCommand = new RelayCommand(Add);
        }

        private void Add(object obj)
        {
            var a = int.Parse(FirstNumber);
            var b = int.Parse(SecondNumber);

            Result = (a + b).ToString();
        }
        

        // Use strings to simplify demo code (so no val converter)
        public string FirstNumber { get; set; }
        public string SecondNumber { get; set; }
        public string Result { get; set; }

        public ICommand AddCommand { get; private set; }
    }
}

Notice the [ImplementPropertyChanged] attribute which means INotifyPropertyChanged will be automatically implemented for us. Notice that it’s much easier to see what’s essential in the viewmodel without all the noise of INotifyPropertyChanged.

If we decompile the Windows store app we can see the implementation:

namespace UniFodyDemo
{
    internal class CalculatorViewModel : INotifyPropertyChanged
    {
        public ICommand AddCommand
        {
            get
            {
                return this.u003cAddCommandu003ek__BackingField;
            }
            private set
            {
                if (this.u003cAddCommandu003ek__BackingField == value)
                {
                    return;
                }
                this.u003cAddCommandu003ek__BackingField = value;
                this.OnPropertyChanged("AddCommand");
            }
        }

        public string FirstNumber
        {
            get
            {
                return this.u003cFirstNumberu003ek__BackingField;
            }
            set
            {
                if (String.Equals(this.u003cFirstNumberu003ek__BackingField, value, 4))
                {
                    return;
                }
                this.u003cFirstNumberu003ek__BackingField = value;
                this.OnPropertyChanged("FirstNumber");
            }
        }

        public string Result
        {
            get
            {
                return this.u003cResultu003ek__BackingField;
            }
            set
            {
                if (String.Equals(this.u003cResultu003ek__BackingField, value, 4))
                {
                    return;
                }
                this.u003cResultu003ek__BackingField = value;
                this.OnPropertyChanged("Result");
            }
        }

        public string SecondNumber
        {
            get
            {
                return this.u003cSecondNumberu003ek__BackingField;
            }
            set
            {
                if (String.Equals(this.u003cSecondNumberu003ek__BackingField, value, 4))
                {
                    return;
                }
                this.u003cSecondNumberu003ek__BackingField = value;
                this.OnPropertyChanged("SecondNumber");
            }
        }

        public CalculatorViewModel()
        {
            this.FirstNumber = "5";
            this.SecondNumber = "10";
            this.Result = "";
            this.AddCommand = new RelayCommand(new Action<object>(this, CalculatorViewModel.Add));
        }

        private void Add(object obj)
        {
            int num = Int32.Parse(this.FirstNumber);
            int num1 = Int32.Parse(this.SecondNumber);
            this.Result = (num + num1).ToString();
        }

        public virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler propertyChangedEventHandler = this.PropertyChanged;
            if (propertyChangedEventHandler != null)
            {
                propertyChangedEventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

So not only with Universal projects can we share code via the shared code project, adding Fody into the mix is even more awesome.

For a list of available addins or to contribute (or even create your own addin) check out the GitHub project site.

Also to learn more about Fody feel free to check out my Pluralsight course.

SHARE:

Write Less Repetitive Boilerplate Code with Fody

My newest Pluralsight course on Fody was just released.

Fody is a tool that frees us up from having to write repetitive boilerplate code. For example we can automate IDisposable implementation or automatically add Equals(), GetHashCode() and equality operators.

Fody is not one tool, but a collection of individual “addins” around the core Fody, with the core GitHub members: Simon Cropp, Rafał Jasica, and Cameron MacFarland.

Automatically Implementing Equality

As an example of what’s possible with Fody, we can auto-implement equality.

So first off we install the Equals Fody addin via NuGet:

PM> Install-Package Equals.Fody

Now we can add the [Equals] attribute to indicate that we want to auto-implement equality.

We can opt-out specific properties so they won’t be considered during equality by applying the [IgnoreDuringEquals] attribute.

We can also provide custom equality logic by creating a method and decorating it with the [CustomEqualsInternal] attribute. So for example if either altitude is –1 then consider altitudes equal.

The following code shows these attributes in action:

[Equals]
public class Location
{
    [IgnoreDuringEquals] 
    public int Altitude { get; set; }
    
    public int Lat { get; set; }
    public int Long { get; set; }

    [CustomEqualsInternal]
    private bool CustomEqualsLogic(Location other)
    {
        // this method is evaluated if the other auto-equal properties are equal

        if (this.Altitude == other.Altitude)
        {
            return true;
        }

        if (this.Altitude == -1 || other.Altitude == -1)
        {
            return true;
        }

        return false;
    } 
}

For a list of available addins or to contribute (or even create your own addin) check out the GitHub project site.

To learn more about how Fody works, how to use some of the available addins, and how to create your own check out my Pluralsight course.

SHARE:

Kill CapsLock with AutoHotkey

capslock key on a keyboard

How often do you actually use CapsLock – deliberately that is?

Most of the time I hit it accidentally then END UP SHOUTING in emails or Tweets. It’s especially a pain sometimes while coding…

We can stop CapsLock from doing it’s capsy thing using AutoHotkey.

The following remaps the CapsLock key to nothing:

Capslock::

Now the CapsLock key doesn’t do anything, the caps LED on the keyboard doesn’t even light up.

We could also remap CapsLock to F6, so we can hit CapsLock in Visual Studio to do a build:

Capslock::F6

This will trigger F6 in all applications, not just in Visual Studio.

To limit the remapping to only when we are in Visual Studio:

SetTitleMatchMode, 2
#IfWinActive Microsoft Visual Studio
Capslock::F6
#IfWinActive

Here the remapping only occurs if the window title contains “Microsoft Visual Studio”. (The SetTitleMatchMode command tells AutoHotKey to look in any part of the title for the match.

Now, outside of Visual Studio, CapsLock behaves normally, but inside VS it will perform a build.

 

To learn more about AutoHotkey, check out my Pluralsight course: Personal Productivity & Performance Tools for Windows Developers.

SHARE:

Doing an Internet Search for the Current Word in Visual Studio with AutoHotkey

I got bored in Visual Studio double clicking a class, copying to clipboard, then heading to browser then pasting into search box.

I wanted to be able to quickly search for something (e.g. in Google) for whatever word the cursor was currently in. Also in other applications.

I have a Microsoft keyboard that has a calculator key that normally opens the Calculator application. I’ve never ever used this and hadn’t even noticed it until now.

image of the calculator key on my keyboard

To map this key in AutoHotkey, “Launch_App2” can be used, so to trigger a script whenever it’s pressed: Launch_App2::

I also wanted the default behaviour to automatically go to the first result. Pressing CTRL-calckey just does a normal search and lists all the results for me to peruse.

Here’s the script – note that it’s a bit rough and ready, for example it uses the clipboard (CTRL-C) so this will overwrite anything you have in it. It also won’t work if the cursor is at start of line, etc.

Launch_App2:: ; Do an I'm Feeling Lucky Google search when calc key pressed
  Clipboard := 

  SendInput, ^{LEFT}^+{RIGHT}
  SendInput, ^c
  ClipWait, 1

  if !(ErrorLevel)  { 
      Run, % "https://www.google.com/search?hl=en&btnI=I%27m+Feeling+Lucky&&q=" Clipboard
  }
return



^Launch_App2:: ; Do a normal Google search when calc key pressed
  Clipboard := 

  SendInput, ^{LEFT}^+{RIGHT}
  SendInput, ^c
  ClipWait, 1

  if !(ErrorLevel)  { 
      Run, % "https://www.google.com/search?hl=en&q=" Clipboard
  }
return

Now if i have my cursor in the word “ActionResult” in Visual Studio, hitting the calculator key takes me to MSDN http://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult%28v=vs.118%29.aspx as this is the first Google search result for “ActionResult”.

 

If you’ve never used AutoHotkey before, to get started check out my Pluralsight course.

SHARE:

Using Glide Paths to Increase Productivity

I first became aware of the concept of “glide paths” in Getting Results the Agile Way. A glide path is an aeronautical term meaning: “the course followed by an aircraft or spacecraft when descending for a landing.” – Dictionary.com

Usually this refers to a low/no power descent which requires little effort.

Applying this concept to the work we do essentially means doing the harder/boring/tougher/difficult/unpleasant things earlier in the week so that towards the end of the week we are “gliding”, with less effort required as we’ve already done the worse tasks.

In addition to applying glide paths to the week, we can apply this to individual days: doing the tougher things at the start so as we get closer to finishing for the day, our tasks get easier.

The same thinking can also be employed by agile teams, for example doing the harder things earlier in the sprint.

The following diagram shows as we get more tired during the week, how the duration of a given task may increase:

image

This is not always the case obviously, everyone has different energy patterns, but becoming more self-aware we can apply ourselves to different kinds of work at the times where we get get the most output. Also it’s interesting that it may be better to do tasks requiring creativity when we’re tired.

Glide paths assume that we have some autonomy over the prioritisation of our tasks, even when we do have autonomy we my have little choice sometimes about when things get done. Even so, glide paths are a useful concept to have in our productivity toolboxes.

SHARE:

Save Keystrokes with AutoHotkey Hotstrings

AutoHotkey is a free open source tool that does all kinds of cool things, one of which is hotstrings.

Hotstrings allow us to define shorthand phrases that get expanded into full text. For things we type often, creating hotstrings can save us valuable keystrokes.

Once AutoHotkey is installed, we can edit the script and add our hotstrings.

So, if we typed “dontcodetired.com” often, we could define a hotstring like this:

::dct::dontcodetired.com

Now when we type “dct” followed by an ending key such as space or enter, the “dct” gets auto-replaced with “dontcodetired.com”.

If we want the replacement to happen as soon as the last character is typed (in this case the “t”) and not have to press an ending key we add an asterisk after the first colon:

:*:dct::dontcodetired.com

Now as soon as the “t” key is pressed the replacement happens immediately.

 

To find out more about hotstrings and the other cool features of AutoHotkey, check out my Pluralsight course: Personal Productivity & Performance Tools for Windows Developers

SHARE:

Kill Your Productivity Demons with my New Pluralsight Course

My new Pluralsight course Personal Productivity & Performance Tools for Windows Developers “get more done in less time” has just been released.

It covers a range of developer-focused and general productivity tools that you can mix and match to suit your way of working.

“We’re constantly under pressure to be more productive. Learn how to use these tools to improve your productivity, streamline your workflows, and get more done in less time. ”

The course consists of:

  • Reduce Typing with AutoHotkey
  • LINQPad – A C# / VB.NET Scratchpad
  • Starting Programs and Websites with SlickRun
  • Take Control of your Clipboard with ClipX
  • Remember What you Did with TimeSnapper
  • Making the Internet Work for You with IFTTT
  • Free Image Editing with Paint.NET

You can find this course along with my other courses on the Pluralsight author page.

SHARE:

What are Your 3 Wins for 2014?

The idea of "the power of three" is a universal concept; it can be seen anywhere from religion (The Holy Trinity, Triquetra, etc.) to childhood learning ("ABC", "123") to entertainment (The Three Musketeers, The Three Stooges, etc.) to project management (the scope-cost-schedule triangle).

One simple way to exploit the power of three is to define outcomes/wins/achievements. These "three wins" can be at any level:

  • Three wins for the project
  • Three wins for the year
  • Three wins for the month
  • Three wins for the week
  • Three wins for today

The three chosen things should not be simple tasks to be ticked off, they should be things that feel like a "win" and give a real sense of progress and satisfaction.

The "wins" should be realistic and achievable.

Getting Results the Agile Way by J. D. Meier makes extensive use of the power of three with its "Monday Vision, Daily Outcomes, Friday Reflection" and three types of "Hot Spot".

The power of three can also be applied to individual items of work/features being developed, for example a feature can be evaluated by: user value, business value, technical value. In agile team retrospectives the power of three can be used to decide: what went well, what didn't go well, what will be improved upon in the next iteration.

(the above is an excerpt from my book Keeping Software Soft)

My 3 Wins for 2014

These are my 3 (professional) wins for 2014 (in no particular order):

While these aren’t my only wins for the year, they are things that I feel if I accomplish them, when I see in 2015 I can look back and be content.

It’s also important to be flexible with plans, if professional or personal events happen that mean I really can’t accomplish these then that’s ok: no plan survives contact with the enemy.

 

Make some time to think about and write down your 3 wins for 2014 and feel free to share them in the comments.

SHARE: