Windows Tile Updater (Part 4 - rationalise the code)

May 20, 2014

From Part 3 of this tutorial, we finished with a small program running on both Windows 8.1 and Phone 8. It shared most of its business logic, but replicated the XAML. It had an ugly even handler to deal with the single action that it performed. In this post, I’m going to attempt to change this to use the MVVM architecture. I’m also going to do this without using a third party framework.

MVVM

If we are to migrate this to an MVVM pattern, then we will need to do the following: 1. Create a view model 2. Bind the view, to the view model 3. Create a model (the business / tile logic that we have is already a model of sorts).

View Model

I usually find it easier to work from the View Model first.

Note: I’d normally create this as a separate PCL, but it would appear that shared projects are limited in that they cannot reference any other projects. I found no documentation from MS to say why, or even confirm this was the case. This may well be the subject of a future post.

Anyway, we can create the view model in the shared project:

createmodelinsharedproject

Let’s start with the properties:



namespace TileUpdater.ViewModel
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private static MainViewModel \_mvm;
        public static MainViewModel MVM
        {
            get
            {
                if (\_mvm == null)
                    \_mvm = new MainViewModel();

                return \_mvm;
            }
        }

        private string \_imagePath = @"c:locationimage.png";
        public string ImagePath
        {
            get { return \_imagePath; }
            set
            {
                SetProperty(ref \_imagePath, value);
            }
        }

        private string \_displayText;
        public string DisplayText
        {
            get { return \_displayText; }
            set
            {
                SetProperty(ref \_displayText, value);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected bool SetProperty(ref T storage, T value, [CallerMemberName] String propertyName = null)
        {
            if (Equals(storage, value))
            {
                return false;
            }

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

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

And bind them to the Windows 8 view:

[sourcecode language=“XML”]

        Image            
        
    
    
    Text
        
    

    Update



**Quick explanation**

I simply created a singleton instance of the view model.  Did I have to create a singleton? No - there's a hundred different ways I could have done this; if I had several view models then you could create a small dictionary with them in (in the style of MVVMLight).  I specifically didn't want to use a framework here, and I didn't want to overcomplicate - say what you like about singletons, but they are simple.

**Now let's bind the phone**

Take the XAML in the Windows 8 XAML and paste it into MainPage.xaml:

[sourcecode language="XML"]
…
DataContext="{Binding MVM, Source={StaticResource MainViewModel}}">
    Image            
            
        
        
        Text
            
        

        Update
    

Command Binding

The next step is to bind the commands. MVVM Light allows RelayCommand for this purpose, but let’s see what we can do on our own.

The first step is to bind the command. For now, let’s just do this in the Windows 8 MainPage.xaml:


        
        Update

We’ve now bound the command, but have nothing to bind. Without a framework, this is very much a matter of rolling your own. First, you need to add the command:

addupdatecommand

The implementation is quite simple:


namespace TileUpdater.ViewModel
{
    class UpdateCommand : ICommand
    {
        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            TileUpdater.UpdateTile.UpdateTileImage();
        }
    }
}

Finally, just link this up the the ViewModel (TileUpdater.Shared):


        private ICommand \_updateCommand;
        public ICommand UpdateCommand
        {
            get
            {
                if (\_updateCommand == null)
                {
                    \_updateCommand = new UpdateCommand();
                }
                return \_updateCommand;
            }
            set { \_updateCommand = value; }
        }

Needless to say that we need to make the same change in the phone app. The XAML for MainPage should be exactly the same:


        
        Update
    

What about the Model - isn’t this just VVM?

Okay - so, we’re now basically using the MVVM pattern. We don’t technically have a Model, though. Actually, TileUpdater is really the Model, so let’s simply call it one:

justcallitamodel

Conclusion

Now we’re running an MVVM pattern and sharing most of the code. However, there’s a lot of duplicate XAML, and the UI is a bit scrappy, so We’ll have a look at that in the next post.



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024