Navigating in Xamarin

I was listening to a podcast (Merge Conflict) recently about the latest changes in Xamarin, and being a curious soul, decided it was time to at least understand what was going on. This time, the big new feature was the Xamarin Live Player which promises much faster debugging through your actual phone! Instead of being stuck using the creaky old Android emulator on Windows, or waiting 2 – 5 minutes on every build with your phone plugged in, you could now, with the power of the internet, debug wirelessly almost instantly. Obviously, I was suspicious, but this sounded like fun, so I jumped in.

Getting setup was a bit of a chore, I will admit. Most of the trouble was linked to being an early adopter. You see, Xamarin Live Player wasn’t truly released yet, just part of the latest preview of Visual Studio (v15.3 to be exact). So I had to get that, install almost all features (say goodbye to about 40GB on your hard drive, sorry ultrabook owners), and then I was basically ready to go. The final step was installing their app on my phone, and I was ready to go.

Within about 10 minutes I had the demo project running on my phone, pretty good I thought. I used the Master/Detail project template and that came with some basic navigation to boot. Everything looked great…but was it?

Being a big fan of MVVM, I really have 3 things I need in place before I can start building an application.

  1. A base class implementing INotifyPropertyChanged. Luckily this project came with one called ObservableObject.
  2. A class implementing ICommand. Again, Xamarin has us covered here, with their implementation imaginatively named Command.
  3. Some kind of ViewModel first navigation system, which appears to be missing.

So, before I get into what’s missing, I want to say that obviously, it’s not Xamarin’s job to create this stuff for us. I don’t need to be spoon-fed. Also, I get that they’re trying to set us up with a working system to get us rolling, but I don’t think this is it.

I’ve never liked View-first navigation in MVVM apps. I don’t really get how you’re supposed to be able to pass anything around, unless you’re constantly creating a View, then passing the newly created ViewModel into that in the constructor. Gross. Unfortunately, that’s what this demo app does, and it took me a few hours to figure out what everything was and what was doing what, before I realized I needed a better way. In the template you get, they’re basically doing navigation from events in the code-behind of the views (or pages in this case). Again, not a fan.

My first instinct was to do my old favorite, using DataTemplates, and just defining the View / ViewModel pairs explicitly in Xaml somewhere and being done with it. Unfortunately, it looked like this wasn’t going to fly in Xamarin.

So I did what I always do, started googling it. And it worked. I came across a library called VMFirstNav. It contained most of what I wanted, but had a little more in it than I wanted. Using their implementation, you have to make all Views implement an interface telling the library what ViewModel to link it to, and then all ViewModels have to implement another interface. It wasn’t a dealbreaker, but I wanted to see what he was actually doing. The nice thing of all that was that it would automagically figure out what View to load when you change (or push) to a new ViewModel.

This is where I want to thank CodeMillMatt. Without his code, I would have taken a lot longer to figure out how this all works. It’s good stuff dude.

OK, so what I did was take his library and just boil it down to the one important class, the NavigationService, which I named Navigator. I didn’t bother making a new github project, or putting it in Nuget, as I don’t think this is really finished. I could see a need for more features depending on what you need, but this is at least a solid starting point.

Here’s the code for the class –

And here’s how to use it, once you’ve got it in place. It has a static constructor, so it’s essentially a singleton, so you don’t need to go passing it in and out of every class. It’s a little more decoupled, but I prefer it that way.


There’s 2 ways of using it.

  1. Explicitly specify all the View / View Model pairs on startup. In the past I’ve liked this method as at least you know where they are and how it works. The other advantage of this is you can name these classes whatever you want.
     private void SetupAllViewToViewModelPairs()
     {
         var nav = Navigator.Instance;
    
         nav.Register(typeof(LoggingViewModel), typeof(LoggingView));
         nav.Register(typeof(AnotherViewModel), typeof(AnotherView));
     }
    
  2. Follow a simple naming convention, and the service will automagically figure out what View to load when you tell it to load a certain View Model. The convention can be changed (it’s your code now after all). As long as you follow the scheme below, you’ll be good.
     [ClassName]View.xaml
     [ClassName]ViewModel.cs
    

OK, then to use it, you’re basically just doing the following –

var vm = new [ClassName]ViewModel();
await Navigator.Instance.PushAsync(vm);

Easy.

Bear in mind, there is no error checking on this code, so maybe tidy that up a little if you plan on using it. The only part you would need to be more careful of is probably the automatic View locating part.

Just to wrap this up. I played with Xamarin for a couple of days, but found the limitations to be too hard to work with. I’m sure there’s a lot of uses for it, but we don’t do a lot with web services at my work, so I haven’t got any excuses to work with it.

If you’ve got any comments on the code, or you’ve built anything cool in Xamarin that you’d like to show off, let me know in the comments.

Advertisements

Prototyping a puzzle game in C#

I had an idea recently for a puzzle game. Now I’ve had ideas for games in the past, but after second inspection they were either way too complicated for me to take on by myself or the idea didn’t hold up. This one, however, seemed to be a winner, so I decided to spend some time throwing together a prototype.

Over the last year I’ve taken a couple of online courses about Unity with the hope that I can pick up enough skills to be able to create my own game someday. I think this could be the perfect game to finally give it a shot. The problem for me is that I have trouble remembering the details of Unity while focusing on trying to make a real prototype of this game. Something’s going to slip, either I spend every 2 minutes googling on how to do basic things, or I spent my time focusing on the actualy game logic. In this case, the game logic was going to be complex, so I wanted 100% focus on that for now.

In my day job I work with WPF and C# all day long so I’m very comfortable with it (“very comfortable” is about as much praise as I’ll ever give myself in any skill, I was asked in an interview once to rate my skills in C# and I ended up saying 6/10, for a job I wanted). So the obvious thing for me was to throw together a prototype using what I work best with, and that’s what I’m going to talk about here.

First thing you’ll need is an MVVM library. Not to toot my own horn, but I created JustMVVM for this purpose, so feel free to use it if you want, it’s available on Nuget too.

This puzzle game idea I have could be generically described as similar to Tetris, so I have a basic grid and some blocks. Here’s the View layout, I’ve stripped out some of the less useful stuff.

<Window xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:local="clr-namespace:PuzzlePrototype"
        Title="MainWindow"
        SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen"
        mc:Ignorable="d">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <ItemsControl x:Name="GameGrid"
                      ItemsSource="{Binding Blocks}">

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Width="{Binding Width}"
                            Height="{Binding Height}"
                            Background="#FF444444">
                    </Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Canvas.Bottom"
                            Value="{Binding Bottom}" />
                    <Setter Property="Canvas.Left"
                            Value="{Binding Left}" />
                </Style>
            </ItemsControl.ItemContainerStyle>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Rectangle Canvas.Left="{Binding Left}"
                               Canvas.Bottom="{Binding Bottom}"
                               Width="{Binding BlockSize}"
                               Height="{Binding BlockSize}"
                               Stroke="White">
                        <Rectangle.Fill>
                            <SolidColorBrush Color="{Binding Color}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>

The ItemsControl just contains a collection of blocks, allowing you to bind them to the ViewModel using MVVM.

There’s also a little magic that can be added to the Canvas inside the ItemsControl.ItemsPanel called FluidMoveBehavior. If you add this to the View, you’ll automatically get animated transitions when the blocks move positions. It’s pretty much up to you if you want to make a simple blocky game, or want a little more smooth animation in it. Here’s the FluidMoveBehavior

<Canvas Width="{Binding Width}"
        Height="{Binding Height}"
        Background="#FF444444">
    <i:Interaction.Behaviors>
        <ei:FluidMoveBehavior AppliesTo="Children"
                                Duration="0:0:0.5">
            <ei:FluidMoveBehavior.EaseY>
                <SineEase EasingMode="EaseIn" />
            </ei:FluidMoveBehavior.EaseY>
            <ei:FluidMoveBehavior.EaseX>
                <SineEase EasingMode="EaseIn" />
            </ei:FluidMoveBehavior.EaseX>
        </ei:FluidMoveBehavior>
    </i:Interaction.Behaviors>
</Canvas>

The SineEase can be substituted for other easing functions.

Here’s the bare bones for the ViewModel to get things going –

public class MainWindowViewModel : MVVMBase
{
    public const int NUM_COLS = 10;
    public const int NUM_ROWS = 16;
    public const int BLOCK = 40;

    private ObservableCollection<Block> _blocks;
    public ObservableCollection<Block> Blocks
    {
        get { return _blocks; }
        set
        {
            _blocks = value;
            OnPropertyChanged();
        }
    }

    public double Width { get { return NUM_COLS * BLOCK; } }
    public double Height { get { return NUM_ROWS * BLOCK; } }

    public MainWindowViewModel()
    {
        Blocks = new ObservableCollection<Block>();
    }
}

For this prototype, it’s easiest to have all your grid size code in one place, so I’ve stored them in constants at the top. The Width and Height are bound to the view so it’ll scale appropriately. In this case, we’re creating a window 400 x 640, where each block is 40 x 40.

This is also where I ended up throwing all of my code while I was testing this out, but feel free to make it as complicated or simple as you place.

Finally, the last class required is Block.cs.

public class Block : MVVMBase
{
    public static List<Color> ColorList = new List<Color>()
    {
        (Color)ColorConverter.ConvertFromString("#860DFF"),
        (Color)ColorConverter.ConvertFromString("#3D0CE8"),
        (Color)ColorConverter.ConvertFromString("#000CFF"),
        (Color)ColorConverter.ConvertFromString("#0C50E8"),
        (Color)ColorConverter.ConvertFromString("#0D97FF")
    };

    public int BlockSize { get; set; } = MainWindowViewModel.BLOCK;

    private double _bottom;
    public double Bottom
    {
        get { return _bottom; }
        set
        {
            _bottom = value;
            OnPropertyChanged();
        }
    }

    private double _left;
    public double Left
    {
        get { return _left; }
        set
        {
            _left = value;
            OnPropertyChanged();
        }
    }

    private int _x;
    public int X
    {
        get { return _x; }
        set
        {
            _x = value;
            Left = _x * MainWindowViewModel.BLOCK;
        }
    }

    private int _y;
    public int Y
    {
        get { return _y; }
        set
        {
            _y = value;
            Bottom = _y * MainWindowViewModel.BLOCK;
        }
    }

    public Color Color { get; set; }

    private static Random _random = new Random(DateTime.Now.Millisecond);

    public Block(int x, int y)
        : this(x, y, ColorList[_random.Next(ColorList.Count)])
    { }

    public Block(int x, int y, Color color)
    {
        X = x;
        Y = y;

        Color = color;
    }

    public override string ToString()
    {
        return $"({ X }, {Y}), { Color.ToString() }";
    }
}

There’s not a lot to it really, most of this code just exists to scale your block units (0, 0) to (9, 15) to WPF pixel coordinates.

The reason I created this was to stop myself wasting any of my (little) free time navigating Unity. Hopefully some day in the future I’ll be so proficient in Unity that I won’t need this middle step, but for now it worked perfectly. If and when I’m happy with my game, I’ll make sure it all works and then focus on recreating the hard work in Unity to create the cross-platform game I’m looking for.

Hopefully some of you folks out there can also benefit from creating something in a familiar environment with the language you’re most confortable with.

All this source code is available on Github here.

Let me know what you think in the comments.

Automate Your App Settings View in WPF

 

If you’re anything like me, you’re always coming up with new ideas for applications. Since WPF is my favorite UI framework, I usually end up creating it in C# and WPF. Things go great for a while, the application gets to a working state and I’m ready to preview it to the world (or a friend), but there’s still one thing I need to do – the settings screen.

The requirements for a setting screen can vary depending on the complexity of your application, but even the simplest ones usually have a handful of settings. Every time I get to this stage of the process I end up slacking off and not really finishing it properly.

So, here’s my one-stop solution to never having to create another settings screen ever again. Just implement the steps below and you’ll have a simple settings screen that binds to a class with special attributes to handle some of the finer details. Let’s jump in –

Settings Classes

First we need a simple class to contain our settings. In this example we’ll just stick with 5 settings

public class AppSettings
{
    public string LogFile { get; set; }
    public bool LogAllData { get; set; }
    public bool LightTheme { get; set; }
    public int NumberOfUsers { get; set; }
    public enum eStartupView { get; set; }
}

Now, obviously, you’re probably storing these settings somewhere, either in SQL or some kind of file, but I’ll leave those details up to you.

We want to be able to add some data to these settings so we can display a description of the setting to the user on the Settings screen. There may be some other data you’ll need to add to them to organize the settings or even hide some from the user. To do this, we’re going to create an Attribute class –

public class SettingAttribute : Attribute
{
    public string Description { get; set; }
    public bool Visible { get; set; }
}

Now we can use this attribute class to add the extra information into our settings, so our AppSettings class becomes this

public class AppSettings
{
    [Settings(Description = "Log file location")]
    public string LogFile { get; set; }

    [Settings(Description = "Do you want to log all data?")]
    public bool LogAllData { get; set; }

    [Settings(Description = "Use the light theme?")]
    public bool LightTheme { get; set; }

    [Settings(Description = "How many users are in the system?)]
    public int NumberOfUsers { get; set; }

    [Settings(Description = "What view should we show on startup?")]
    public enum eStartupView { get; set; }
}

ViewModels

Now we can create the ViewModel for the Settings View. The goal in the SettingsViewModel is to read all the properties from AppSettings using reflection and create a list of SettingsItemViewModels. Let’s start with the SettingsItemViewModel. I have it inheriting from MVVMBase which is a base class that inherits INotifyPropertyChanged. If you’re looking for an MVVM framework may I suggest JustMVVM, I wrote it, but it’s the simplest MVVM framework around, and that’s why I did it.

public class SettingsItemViewModel : MVVMBase
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Type SettingType { get; set; }
    public bool IsDirty { get; set; }

    private dynamic _value;
    public dynamic Value
    {
        get { return _value; }
        set
        {
            _value = value;
            OnPropertyChanged();

            IsDirty = true;
        }
    }
}

So, this class above is a generic class that can contain any type of setting. This way we can create a list of them, one for each of the properties in AppSettings. The real key to this is using the dynamic type for the property Value. It allows us to set it generically and then check if afterwards to find out the type. IsDirty can also be useful to tell if the setting was actually changed. We’ll see that below.

Here’s the code for the SettingsViewModel which is the view model for the SettingsView UI.

public class SettingsViewModel : MVVMBase
{
    private ObservableCollection<SettingsItemViewModel> _settings;
    public ObservableCollection<SettingsItemViewModel> Settings
    {
        get { return _settings; }
        set
        {
            _settings = value;
            OnPropertyChanged();
        }
    }

    public SettingsViewModel()
    {
        AppSettings appSettings = GetAppSettings();

        Settings = GetAvailableSettings(appSettings);
    }

    public ObservableCollection<SettingsItemViewModel> GetAvailableSettings(Dictionary<string, object> settings)
    {
        var settingsView = new ObservableCollection<SettingsItemViewModel>();

        foreach (var prop in typeof(AppSettings).GetProperties())
        {
            var settingItem = new SettingsItemViewModel();

            foreach (var customAttData in prop.GetCustomAttributesData())
            {
                foreach (var item in customAttData.NamedArguments)
                {
                    var name = item.MemberInfo.Name;

                    if (name == "Description")
                        settingItem.Description = item.TypedValue.Value.ToString();
                }
            }

            settingItem.Name = prop.Name;
            settingItem.Value = settings[prop.Name];

            // Get type once value is set, value will get type dynamically
            settingItem.SettingType = settingsItem.Value.GetType();

            settingItem.IsDirty = false;

            settingsView.Add(settingItem);
        }

        return settingsView;
    }
}

OK, we’ve now got our ObservableCollection<SettingsItemViewModel> ready to go for the View. Let’s take a look at what needs to happen there.

View

OK, the View is pretty straight forward. We’re going to use an ItemsControl to contain our list of settings and we’ll use DataTemplates to figure out what view to display for each setting. Hopefully this will become more clear after you look at the code –

<Grid>
    <ItemsControl ItemsSource="{Binding Settings}">        
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type vm:SettingsItemViewModel}">
                <ContentControl Content="{Binding }">
                    <ContentControl.Style>
                        <Style TargetType="{x:Type ContentControl}">
                            <Style.Triggers>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:Boolean}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource BooleanSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:Int32}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource IntegerSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:Double}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource DoubleSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType}"
                                             Value="{x:Type sys:String}">
                                    <Setter Property="ContentTemplate" Value="{StaticResource StringSettingTemplate}" />
                                </DataTrigger>

                                <DataTrigger Binding="{Binding SettingType,
                                                               Converter={StaticResource IsEnumeratorConverter}}"
                                             Value="True">
                                    <Setter Property="ContentTemplate" Value="{StaticResource EnumSettingTemplate}" />
                                </DataTrigger>

                            </Style.Triggers>
                        </Style>
                    </ContentControl.Style>
                </ContentControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

The ContentControl inside the ItemsControl has a bunch of triggers that displays a different DataTemplate based on the SettingType of the SettingsItem. This allows us to have different views for each type. Obviously the view for a Boolean settings will be some kind of a checkbox, while the view for an enum would probably be a combobox.

Here are the data templates used to make this magic happen. If you don’t know too much about data templates, this is a good resources. These need to be placed in the resources section somewhere in the View. In this case I put it in the ItemsControl.Resources section.

<ItemsControl.Resources>

    <DataTemplate x:Key="BooleanSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <CheckBox HorizontalAlignment="Left"
                      Content=""
                      IsChecked="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="IntegerSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <wpf:SFNumberTextBox HorizontalAlignment="Left"
                                 Interval="1"
                                 StringFormat="N0"
                                 ValueInt="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="DoubleSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <wpf:SFNumberTextBox HorizontalAlignment="Left"
                                 Interval="0.5"
                                 StringFormat="N1"
                                 Value="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="StringSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <TextBox HorizontalAlignment="Left"
                     wpfab:TextFieldExt.ClearTextButton="True"
                     Text="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

    <DataTemplate x:Key="EnumSettingTemplate">
        <UniformGrid Columns="2"
                     Rows="1">
            <Label HorizontalAlignment="Right"
                   Content="{Binding Description}" />
            <ComboBox ItemsSource="{Binding SettingType,
                                            Converter={StaticResource EnumToArrayConverter}}"
                      SelectedItem="{Binding Value}" />
        </UniformGrid>
    </DataTemplate>

</ItemsControl.Resources>

Alright. Everything’s linked up now. Obviously you can add to this if you have more complicated settings. Some settings may even be complete other classes. Either way, this setup should work pretty smoothly for you.

Converters

Here’s a couple of extra pieces that make it easier to use enums with comboboxes for settings (I’m assuming you have some). They’re just a couple of simple converters that let you bind to an enum without having to explicitly mention the enum type.

public class IsEnumeratorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Type))
            return false;

        var type = value as Type;

        return type.IsEnum;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


public class EnumToArrayConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Type))
            return new List<string>();

        return Enum.GetValues(value as Type);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

That’s it. Let me know what you think in the comments. I’m always looking for feedback. I’ve been thinking of some variation of this setup for a while now, and I’m looking forward to never manually creating another settings screen ever again.

DataContext, Data Templates and Data Template Selectors

I spent some time today working on DataTemplateSelectors. I’d never used them before, but it made me think about all the different ways there are to set the DataContext in WPF. After talking through this with a friend, I realized that maybe some of these minor nuances aren’t very clear. I figured if I write about it, at least I can reference it again later when I forget.

OK, my first assumption here is that you’re being a good programmer and using MVVM, this is WPF after all.

Binding To Code-Behind

This is the most basic kind of binding. When you first learn MVVM, this is probably going to be your first step. Binding to code-behind just requires you to set your DataContext to the xaml.cs file attached to your View –

<Window .....
        DataContext="{Binding RelativeSource={RelativeSource Self}}">           
</Window>

In the long run I don’t recommend this one, you’re always going to want to bind a View to a ViewModel in a separate class. It just makes it so much cleaner. This leads to my next header

Binding To ViewModel

This one is really similar to binding to your code behind. The only difference here is that instead of binding to yourself, you’re binding to your View Model. Simple right, OK, here’s the code –

<Window x:Class="MyProgram.MainWindow"
        xmlns:local="clr-namespace:MyProgram"
        mc:Ignorable="d">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
</Window>

Make sure to get the correct namespace (in this case local) of your View Model. When using this style of datacontext setting, you’re going to have to do this for each and every View. At first this might seem OK, but the further into this you get, the more cumbersome this method becomes.

OK, onto the next method; DataTemplates!

Binding Using DataTemplates

DataTemplates are used all over WPF (seriously, you should take a look into how awesome data templating is in ListViews if you don’t believe me). When it comes to Views and View Models the data template allows you to load your Views by specifying the View Model you want. Instead of loading View first, you can call the View Model (along with it’s constructor) and the ContentPresenter will figure out what View to serve up alongside it.

The beauty of this is you can now pass around data between your view models, making it easier to structure your program.

You still need to set the DataContext of your initial entry point View. In the case above it’s the MainWindow and MainWindowViewModel. So, even in this method, make sure to set the DataContext first.

Now, add some kind of presenter (it can be a ContentPresenter, ContentControl or UserControl). This will be the View Controller that will change out the different views according to your bindings. Here’s the code for the View –

<Window x:Class="MyProgram.MainWindow"
        xmlns:local="clr-namespace:MyProgram"
        mc:Ignorable="d">

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <ContentPresenter Content="{Binding View}" />
    </Grid>
</Window>

Here’s the code for your View Model (I’m not including the INotifyPropertyChanged interface, I’m assuming you’ve got that figured out by now, but if you’re looking for a framework, try JustMVVM). MVVMBase is just a base class that all View Models must inherit from.

class MainWindowViewModel : MVVMBase
{
    private MVVMBase _currentViewModel;
    public MVVMBase CurrentViewModel
    {
        get { return _currentViewModel; }
        set
        {
                _currentViewModel = value;
                OnPropertyChanged();
        }
    }

    public MainWindowViewModel()
    {
        // Setting View to Home screen
        CurrentViewModel = new HomeViewModel();
    }
}

For the application to figure out what view to load for the ContentPresenter, we need to add a Data Template. The simplest place to put this is in App.xaml, then it’ll work throughout the entire application, but in reality you can put this in any Resources section

Below are 3 different data templates for 3 different views.

<Application x:Class="MyProgram.App"
             xmlns:view="clr-namespace:MyProgram.View"
             xmlns:viewmodel="clr-namespace:MyProgram.ViewModel"
             Startup="Application_Startup"
             StartupUri="MainWindow.xaml">

    <Application.Resources>

        <DataTemplate DataType="{x:Type viewmodel:HomeViewModel}">
            <view:Home />
        </DataTemplate>

        <DataTemplate DataType="{x:Type viewmodel:SettingsViewModel}">
            <view:Settings />
        </DataTemplate>

        <DataTemplate DataType="{x:Type viewmodel:HelpViewModel}">
            <view:Help />
        </DataTemplate>

    </Application.Resources>
</Application>

For most of my applications that I’ve worked on, this has worked out great. I have a single spot where I put all my data templates and then I’m in complete control over what views are being loaded. There are occasional situations that require an even more complicated solution, so here we go, my final option, the DataTemplateSelector.

Data Template Selector

In theory this is another alternative to using Data Templates, but it gives a little more control over the issue. Sometimes a need arises where you have multiple Views for a single View Model, or you’ve created a generic form of ViewModel<T> but you can’t define a DataTemplate for generics in XAML. In this case, you can create a Data Template Selector, which allows you to select the associated View template in code.

Here’s some example code of the Selector –

public class CustomDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate HomeTemplate { get; set; }
    public DataTemplate SettingsTemplate { get; set; }
    public DataTemplate HelpTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item == null)
            return base.SelectTemplate(item, container);

        var viewModel = item as PropertyChangedBase;
        var viewModelType = viewModel.GetType();

        if (viewModelType.IsGenericType && viewModelType.GetGenericTypeDefinition() == typeof(HomeViewModel<>))
                return HomeTemplate;

        else if (viewModelType == typeof(SettingsViewModel))
            return SettingsTemplate;

        else if (viewModelType == typeof(HelpViewModel))
            return HelpTemplate;

        else
            return base.SelectTemplate(item, container);
    }
}

Let’s unpack this a little bit. The properties at the top can be set in the XAML to the data templates we created in the previous section (see below for how it’s done). The first part of the if statement shows how you can handle a generic type for a template selector. This means that any HomeViewModel<T> will load the HomeTemplate.

The reason I ended up using this over Data Templates is for the else part at the end. I was creating a library that was to be consumed by others. I wanted to be very specific about what templates were loaded in my library, but also leave open the possibility of other people adding their own templates. I guess I could have created some extensible class that allows people to add more templates, but by calling the base implementation of the DataTemplateSelector

return base.SelectTemplate(item, container);

I don’t have to do anything special, I just let the normal DataTemplates take over again like usual.

Here’s how this Selector was implemented in XAML –

<Grid>
    <Grid.Resources>

        <DataTemplate x:Name="HomeTemplate" >
            <view:Home />
        </DataTemplate>

        <DataTemplate x:Name="SettingsTemplate" >
            <view:Settings />
        </DataTemplate>

        <DataTemplate x:Name="HelpTemplate" >
            <view:Help />
        </DataTemplate>

        <viewmodel:CustomDataTemplateSelector x:Key="ViewTemplateSelector"
                                              HomeTemplate="{StaticResource dialogException}"
                                              SettingsTemplate="{StaticResource dialogOKCancel}"
                                              HelpTemplate="{StaticResource dialogOK}" />

    </Grid.Resources>

    <!--  Dialog User Control  -->
    <ContentPresenter Content="{Binding View}"
                      ContentTemplateSelector="{StaticResource ViewTemplateSelector}" />
</Grid>

And like I said, any other View / View Model templates can either be added to the Template Selector (if you have access to it) or can just be placed in App.xaml like usual.

Well, I think that’s all I’ve got about Data Templates. Hopefully by putting this all together in one place I’ve made somebody’s life easier. If you see anything wrong, let me know in the comments.