How to write more efficient and maintainable C# code

When you are writing your C# applications, you are aware that you want to make your applications as efficient, maintainable, and as scalable as possible. These are some great keywords that look great on blog posts like this, but how do you actually set about achieving this goal? We will look at some simply guidelines which try to make this goal more achievable.

Write single purpose methods

Your methods should have a single purpose… a single task to perform. For example, a single method should not try to access a database, create objects, read text files, and create images. Instead, create a single method for each task.

Why? Multipurpose methods are typically long, hard to read, difficult to maintain and inefficient.

Pros: Reduces reuse, improves readability and maintainability.
Cons: None

Keep methods short

A method should be an absolute maximum of 50 lines long. Methods that are longer than this are typically multipurpose, which is bad. You want your code to be reusable where possible.

Pros: More maintainable code, which is more reusable.
Cons: None.

Keep classes short

Classes should be no more than 300 lines long. If you have a “DocumentHelper” class which creates Microsoft Excel worksheets and calculates data based on data retrieved from an external database, consider splitting this into two classes (Excel Helper and ReportDataHelper)

Pros: Promotes reusability, helps keep classes short.
Cons: None.

Don’t have partial classes

Partial classes were introduced for Windows Forms applications to remove the initialisation logic from the main code behind file. Partial classes should not be used in any other scenario. Partial classes should not be used to reduce the length of your classes.

Pros: Partial classes are very difficult to navigate.
Cons: None.

Resolve all build warnings

You shouldn’t have any build warnings in your project. Build warnings typically lead to errors further down the line. Build warnings typically relate to missing references/assemblies.

A good approach is to treat all build warnings as errors.
Open the project properties dialog, click the build tab, and change “Treat warnings as errors” to “All”. This will also force you to clean up unused private member variables, which is always good.

Avoid optional parameters

What: Optional parameters were introduced to improve COM interoperability.

Example;
When working with Microsoft Office COM interoperability assemblies, prior to optional parameters (and the dynamic keyword), it was necessary to pass in Type.Missing to all method parameters which you wanted to be the default (unsupplied) value.

Old way;

object excel;
object range = excel.get_Range("A1", "B4", 1, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

This, as you can see its messy and very quickly becomes difficult to maintain. Now in newer versions of the Office Interop assemblies, all non-essential values are marked as optional, meaning you can simply write the following;

object excel;
object range = excel.get_Range("A1", "B4", 1);

Pros: In some cases, optional parameters can dramatically reduce code complexity and length. Optional parameters can reduce the number of overloaded versions of the method, thus reducing code duplication.

Cons: Optional parameters are a compile time trick. This is actually no support for optional parameters in IL. So what happens when you compile?

Take the following code snippet;

Take the following code snippet;
public class OptionalParametersTest
{
    public OptionalParametersTest()
    {
        LoadAllCustomers();
    }

<pre><code>public void LoadAllCustomers(bool includeAddressDetails = false)
{
    //Load customers
}
</code></pre>

}

What happens to this code at compile time? The value from the optional parameter is baked into the calling method, as follows;

public class OptionalParametersTest
{
    public OptionalParametersTest()
    {
        LoadAllCustomers(false);
    }

<pre><code>public void LoadAllCustomers(bool includeAddressDetails)
{
    //Load customers
}
</code></pre>

}

In this situation there is no problem. But in the case when the calling method is located in a separate assembly, this is an issue. If the default value is changed from false to true, and the calling assembly is not recompiled, then the calling method is out of sync. This is typically not an issue with websites, as you would normally redeploy the entire website; however, it’s an issue with auto-updating desktop apps as they typically only patch the assemblies that have changed since the previous version.

Remove unused code

If you have source control (such as TFS or GIT) … use it! Remove code, don’t delete it. It isn’t gone forever! Your code can be easily retrieved at a later date.

Reduce nesting

Nesting can reduce the complexity of code, its length and the depth of indention of your lines. The Microsoft coding standards suggest that we should return out of a method at the earliest possible time, for efficiency.

Bad:

private void TryNotToNest(bool hasId)
{
    if (hasId)
    {
        if (DateTime.Now > DateTime.Now.AddDays(-1))
        {
            if (string.Equals(stringA, stringB))
            {
                MessageBox.Show("Matched");
            }
        }
    }
}

Better:

private void TryNotToNest(bool hasId)
{
    if (hasId && DateTime.Now > DateTime.Now.AddDays(-1))
        {
            if (string.Equals(stringA, stringB))
            {
                MessageBox.Show("Matched");
            }
        }
    }
}

Good:

private void TryNotToNest(bool hasId)
{
    if (!hasId) return;
    if (DateTime.Now &lt;= DateTime.Now.AddDays(-1)) return;

<pre><code>if (string.Equals(stringA, stringB))
{
    MessageBox.Show(&amp;quot;Matched&amp;quot;);
}
</code></pre>

}

Hopefully this will help you take a small step towards writing better code! 🙂

WPF Entity Framework Code First migrations

Recently I wrote a WPF application using Entity Framework Code First and released it into the wild.  Shortly after, the business requirements changed and I had to make changes to the model.  Thus, I was introduced to Code First migrations.

I did a lot of research on Code First migrations and could only really find the most simple of examples, and almost robotic documentation on MSDN that provided minimal help. This post aims to provide a clearer view on migrations, and how to properly create them.

Before we can start with migrations, we need to create our normal C# code and then add in Entity Framework using NuGet.  Once done, we can create our first migration and then explore a second migration.

The Code

The code is going to revolve around the common idea of customers and orders.

C# Code Structure

Code structure; An Order has a collection of Product and a Customer, the Customer has a CustomerName. Any properties that are marked as virtual are navigation properties, and are lazy loaded by Entity Framework at runtime.

public class Customer
{
    public int Id { get; set; }
    public int CustomerNameId { get; set; }
    public virtual CustomerName CustomerName { get; set; }
}

public class CustomerName
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual List<Product> Products { get; set; }
    public DateTime Placed { get; set; }
}

With the code structure in place, we can now introduce Entity Framework. Go ahead and use the package manager console, or the library package manager to install Entity Framework.

install-package EntityFramework

Enabling Migrations

Before enabling migrations, ensure that you have a DbContext class that contains a DbSet for use throughout the application;

public class Context : DbContext
{
    public DbSet<Order> Orders { get; set; }
}

Entity Framework uses the DbContext class to determine the structure of your database.

The key to making migrations work properly is to create an initial migration that will set up your database into its initial state when you deploy the application.

In the package manager console window, type the following command;

Enable-Migrations

You will notice that this process has has created a new folder (Migrations), and two new files; (Configuration.cs and InitialCreate, prefixed with a Date/Time stamp)

Entity Framework Initial Create

 

 

A word about seed data

At the time of writing, the current version of Entity Framework is 5.0.0.0 (public release). I have found that seed data does not behave in the way that I expect.

Open Configuration.cs and observe the seed data method;

protected override void Seed(CodeFirstMigrations.Context context)
{
    //  This method will be called after migrating to the latest version.

<pre><code>//  You can use the DbSet&amp;lt;T&amp;gt;.AddOrUpdate() helper extension method 
//  to avoid creating duplicate seed data. E.g.
//
//    context.People.AddOrUpdate(
//      p =&amp;gt; p.FullName,
//      new Person { FullName = &amp;quot;Andrew Peters&amp;quot; },
//      new Person { FullName = &amp;quot;Brice Lambson&amp;quot; },
//      new Person { FullName = &amp;quot;Rowan Miller&amp;quot; }
//    );
//
</code></pre>

}

Note that the comment clearly states that the method will be called directly after migrating to the latest version. I’ve found that, in reality, this method is called every time your application starts up. I suppose this is why the AddOrUpdate extension method was added, to prevent duplicate seed data.

Analysing the Visual Studio IntelliSense documentation closely, its pretty clear what this method expects for the first parameter;

AddOrUpdate Extension Method

CLICK IMAGE TO ENLARGE

For the AddOrUpdate method, we must pass in a parameter that will determine if the seed data is ADDED or UPDATED. Unfortunately, this doesn’t seem to work when passing in the primary key of the table (the Id property). For me, this is a major limitation and hopefully it will be resolved in future releases.

The solution here is to skip the seed data method altogether, and add some logic in the application start-up method to determine if the seed data needs to be added or updated.

The final step is to update your initializer to use the MigrateDatabaseToLatestVersion database initializer;

public class Initializer : MigrateDatabaseToLatestVersion<Context, Configuration>
{
}

You can now deploy your application to your customers, knowing that when the customer runs the program for the first time, the database will be created as you expect and and seed data will also be added.

Your second migration

Your second migration now should be straight forward. Simply go ahead and make the desired changes to your model. We will add the following class;

[Table("CreditCardInformation")]
public class CreditCardInformation
{
    public int Id { get; set; }
    public CreditCardType CreditCardType { get; set; }
    public string CreditCardNumber { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

Note that the Table attribute used above is to ensure that Entity Frameworks pluralisation service doesn’t incorrectly name our table. Add a CreditCardInformation property to Customer.

public class Customer
{
    public int Id { get; set; }
    public int CustomerNameId { get; set; }
    public virtual CustomerName CustomerName { get; set; }
    public virtual CreditCardInformation CreditCardInformation { get; set; }
}

Now you are ready to create a migration. You can name the migration simply by passing the desired name in as a parameter.

Add-Migration AddCreditCardInformation

Your migration will look something like this;

public partial class AddCreditCardInformation : DbMigration
{
    public override void Up()
    {
        CreateTable(
            &quot;dbo.CreditCardInformation&quot;,
            c =&gt; new
                {
                    Id = c.Int(nullable: false, identity: true),
                    CreditCardType = c.Int(nullable: false),
                    CreditCardNumber = c.String(),
                    StartDate = c.DateTime(nullable: false),
                    EndDate = c.DateTime(nullable: false),
                })
            .PrimaryKey(t =&gt; t.Id);

<pre><code>    AddColumn(&amp;quot;dbo.Customers&amp;quot;, &amp;quot;CreditCardInformation_Id&amp;quot;, c =&amp;gt; c.Int());
    AddForeignKey(&amp;quot;dbo.Customers&amp;quot;, &amp;quot;CreditCardInformation_Id&amp;quot;, &amp;quot;dbo.CreditCardInformation&amp;quot;, &amp;quot;Id&amp;quot;);
    CreateIndex(&amp;quot;dbo.Customers&amp;quot;, &amp;quot;CreditCardInformation_Id&amp;quot;);
}

public override void Down()
{
    DropIndex(&amp;quot;dbo.Customers&amp;quot;, new[] { &amp;quot;CreditCardInformation_Id&amp;quot; });
    DropForeignKey(&amp;quot;dbo.Customers&amp;quot;, &amp;quot;CreditCardInformation_Id&amp;quot;, &amp;quot;dbo.CreditCardInformation&amp;quot;);
    DropColumn(&amp;quot;dbo.Customers&amp;quot;, &amp;quot;CreditCardInformation_Id&amp;quot;);
    DropTable(&amp;quot;dbo.CreditCardInformation&amp;quot;);
}
</code></pre>

}

Entity Framework gives us the ability to roll back a migration if needed. When a roll back occurs, the Down method on the migration is called and the changes are reverted.

To perform a rollback, simply run the following command;

Update-Database -TargetMigration:"NameOfMigrationToRollBackTo"

If you try to run the application at this time, you will get the following error message;

The model backing the 'Context' context has changed since the database was created.
Consider using Code First Migrations to update the database.

This is because you need to commit the changes to your database, you can do this using the following command;

Update-Database

Run the application again, and all should work as you expect.

Summary

Entity Framework Code First migrations are an exciting and powerful new feature that will dramatically simplify your deployment and update process. The MigrateDatabaseToLatestVersion database initialization strategy will take care of automatically updating your database to the most current version, and can even help with seed data. Seed data is made easy thanks to a new AddOrUpdate extension method, but is limited in that you cannot use the table primary key as the identifier.

Using StructureMap setter injection to inject repositories into your View Model

This short post is a follow on from an earlier series of posts that discussed how to achieve MVVM purity in WPF using Structure Map.  You may want to check out those posts first before reading this post.  However, if you just generally want to know how to do setter injection using Structure Map, you are in the right place!

A Scenario

It is very common in modern applications to have a repository that does the job of retrieving and saving data from/to your database.

Your repository may look like this;

public interface IRepository&lt;T&gt;
{
    int Count { get; }
}

public class CustomersRepository : IRepository&lt;Customer&gt;
{
    private readonly Random _random = new Random();

<pre><code>public int Count
{
    get { return _random.Next(3, 10); }
}
</code></pre>

}

In the above sample we are simulating retrieving the number of customers that currently exist in our database.

Our view model logic may look something like this;

public class ChildViewModel : BaseViewModel, IChildViewModel
{
    public ChildViewModel(IChildView view, IContainer container)
        : base(view, container)
    {
    }

<pre><code>public IRepository&amp;lt;Customer&amp;gt; CustomersRepository { get; set; }

public int CustomerCount { get; set; }

public override void Load()
{
    CustomerCount = CustomersRepository.Count;
}
</code></pre>

}

When the view model has finished loading, we want to retrieve the number of customers from the repository and display this number to the user. How do we get an instance of CustomersRepository?

Well there are two approaches, this is the first;

public override void Load()
{
    CustomersRepository = ObjectFactory.GetInstance<IRepository<Customer>>();
    CustomerCount = CustomersRepository.Count;
}

You can use the static ObjectFactory.GetInstance() method to get an instance of the repository and set the public property to that value. Don’t get me wrong, this approach works… but it is widely considered to be an anti-pattern.

The second approach is to use setter injection, which basically means that StructureMap will inject a value for that property automatically for you at runtime, so that you don’t have to worry about it.

Bootstrapper

All StructureMap based applications begin with a bootstrapper. Your bootstrapper class will typically be a public static class that calls the ObjectFactory.Initialise() method passing an IInitializationExpression object.

We will need to add our repository to the container so that it can be used thoughout the application;

public static class Bootstrapper
{
    public static void Initialise()
    {
        ObjectFactory.Initialize(OnInitialise);
    }

<pre><code>private static void OnInitialise(IInitializationExpression x)
{
    //Omitted for brevity

    //Add the repository
    x.For&amp;lt;IRepository&amp;lt;Customer&amp;gt;&amp;gt;().Use&amp;lt;CustomersRepository&amp;gt;();

    //Tell StructureMap to automatically inject an instance, whenever it comes across a public property of type IRepository&amp;lt;Customer&amp;gt;
    x.SetAllProperties(y =&amp;gt; y.OfType&amp;lt;IRepository&amp;lt;Customer&amp;gt;&amp;gt;());
}
</code></pre>

}

To make StructureMap take care of the setter injection for us, we simply needed to call the SetAllProperties method.

When StructureMap resolves an instance of our view model (or any class for that matter), it inspects it, identifies all the public properties in that class, and looks inside the container to see if it has any matching instances. If it does, it simply injects them for us.

Summary

We can use StructureMap to inject instances of objects into the public properties on our view models simply by calling the SetAllProperties method when initialising the container and telling it what type we want injecting.

Getting started with SQLite and C#

SQLite is a powerful, extremely light-weight transactional SQL database provider. SQLite is free and open source, and it does not require any server processes to handle it. SQLite is cross platform and runs on multiple architectures, making it ideal for use on the major operating systems such as Windows, Mac OS, Linux, and even lower powered devices such as PDAs, MP3 players etc.

Prerequisites

It is possible to get up and running with SQLite quickly in C#, by adding the System.Data.SQLite package to your project.

Open the package manager console window run the following;

Install-package System.Data.SQLite

Or alternatively, right click your project and click Manage NuGet Packages and search the online gallery for System.Data.SQLite.

A Helpful Wrapper Class

I have put together a very simple wrapper class that will get you up and running quickly. Here it is;

public class SQLiteDatabase
{
    private readonly string _dbConnection;

<pre><code>public SQLiteDatabase(string dataSource)
{
    _dbConnection = string.Format(&amp;quot;Data Source={0}&amp;quot;, dataSource);
}

public DataTable GetDataTable(SQLiteCommand command)
{
    if (command == null) throw new ArgumentNullException(&amp;quot;command&amp;quot;);

    using (SQLiteConnection connection = new SQLiteConnection(_dbConnection))
    {
        connection.Open();
        command.Connection = connection;

        using (SQLiteDataReader reader = command.ExecuteReader())
        {
            DataTable result = new DataTable();
            result.Load(reader);
            return result;
        }
    }
}

public SQLiteCommand GetCommand(string sql)
{
    if (string.IsNullOrEmpty(sql))
        throw new ArgumentNullException(&amp;quot;sql&amp;quot;);

    return new SQLiteCommand {CommandText = sql, CommandType = CommandType.Text};
}

public int ExecuteNonQuery(SQLiteCommand command)
{
    if (command == null) throw new ArgumentNullException(&amp;quot;command&amp;quot;);

    using (SQLiteConnection connection = new SQLiteConnection(_dbConnection))
    {
        connection.Open();
        command.Connection = connection;

        return command.ExecuteNonQuery();
    }
}
</code></pre>

}

This wrapper is loosely based on some code written by Mike Duncan.

Usage

The constructor takes the database path (the extension is completely up to you);

SQLiteDatabase database = new SQLiteDatabase("Customers.db");

To execute a standard non query command, you first create your command and call the ExecuteNonQuery method;

SQLiteCommand create = database.GetCommand("CREATE TABLE Customers (Id int PRIMARY KEY, Name nvarchar(256), Address nvarchar(256), PostCode nvarchar(256))");
database.ExecuteNonQuery(create);

SQLiteCommand populate = database.GetCommand("INSERT INTO Customers ('Id', 'Name', 'Address', 'PostCode') VALUES (1, 'Jon Preece', 'My House', 'NN11NN')");
int affected = database.ExecuteNonQuery(populate);

You can retrieve data from the database in the form of the timeless DataTable object;

SQLiteCommand a = database.GetCommand("SELECT * FROM Customers");
DataTable res = database.GetDataTable(a);

Summary

SQLite gives us the ability to write extremely light-weight databases, that have no dependence on third party products or servers. In order to properly utilise SQLite in all but the simplest applications, a major investment would be required to write additional architectural code to load SQL from external SQL files, so as to avoid writing in-line SQL.

If you want to browse your SQLite database, you’ll need the SQLite Browser from Sourceforge.

WPF MVVM IoC containers – Part 2 of 2

The ultimate goal of MVVM is to achieve true separation of concerns, meaning that the various elements of your project know nothing about each other.  It’s virtually impossible to achieve this in an elegant way in WPF without some outside help.

You are reading the second part of this blog post where we will discuss how to use an IoC container properly in a WPF MVVM application.  It is assumed you have either read the first post, or are familiar with the concept of IoC/dependency injection with StructureMap.

Part 0

It’s worth noting just before we get started that you will need to invest a little time to get this set up initially.  That investment will pay off almost immediately as your application begins to scale.

Please take the time to, if you haven’t already, install PropertyChanged.Fody and StructureMap from NuGet.

Core Classes

Start by creating some core classes for use within the rest of your application.  Getting these in a good state early will make architecting the rest of the application a lot easier.

I like to have all my classes inherit from a class called BaseNotification, so that I (thanks to PropertyChanged.Fody) get all the change notification functionality added for free to all my derived classes.

public class BaseNotification : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

Before we can continue, we must add a couple of interfaces to our Core folder. An interface is needed for the actual View (IView) and the View Model (IViewModel) so that we can maintain loose coupling from the Main Window (described later).

public interface IView
{
    object DataContext { get; set; }
}

public interface IViewModel
{
    IView View { get; set; }
}

Note that each view model will have a reference back to the actual view (which is a user control) so as to make finding controls in the visual tree possible, freeing up the parameter on our delegate/relay commands.

Now we need to create our BaseViewModel. Add the following code;

public class BaseViewModel : BaseNotification, IViewModel
{
    public BaseViewModel(IView view, IContainer container)
    {
        View = view;
        View.DataContext = this;

        Container = container;
    }

    public IContainer Container { get; set; }

    public IView View { get; set; }
}

Lets take a second to review what we have here. The constructor is very important as whatever parameters we defined here are going to be injected automatically by the IoC container. We want to pass in an instance of the actual view and a reference back to the IoC container itself. Why? because this gives a means for derived view models to access instances of objects without having to use ObjectFactory.GetInstance, which (as previously discussed) is an anti-pattern. Inside the constructor we set the views data context, which is itself, so as to make data binding possible. This removes the direct relationship between the view and the view model, whilst keeping our code neat, maintainable, and adherent to the DRY principle.

Now over to the window. In this tutorial we are only going to have a single Window, but typically in larger applications you will have multiple windows so its a good idea to get off on the right foot.

We need 2 new interfaces, IWindow and IWindowViewModel. IWindow will represent the Window (MainWindow) and IWindowViewModel is for the windows view model.

public interface IWindow
{
    object DataContext { get; set; }
}

public interface IWindowViewModel
{
    IWindow Window { get; set; }
}

You may have noticed that this is the same set-up as the IView and IViewModel interfaces. A few seconds ago I was telling you to avoid repetition! What gives?! Well over time the Window and your view models will naturally evolve in different directions, so its a good idea to keep them independent of each other from the start.

Now over to the BaseWindowViewModel class, which will act as the data context for your windows;

public class BaseWindowViewModel : BaseNotification, IWindowViewModel
{
    public BaseWindowViewModel(IWindow window, IContainer container)
    {
        Window = window;
        Window.DataContext = this;

        Container = container;
    }

    public IView View { get; set; }

    public IContainer Container { get; set; }

    public IWindow Window { get; set; }

    protected void ShowView<T>() where T : IViewModel
    {
        View = Container.GetInstance<T>().View;
    }
}

Whilst the BaseWindowViewModel is similar to the BaseViewModel class, there are a few subtle differences here. The window is going to display your view within itself. To make this possible, we need a View property, which can be of type IView as all our views implement this interface. We also have a ShowView method, which retrieves an instance of the view from the container, using the type parameter passed in.

So far our code is looking clean and crisp, without a concrete class in sight. This will make unit testing a breeze later on, as mocking/stubs/fakes will now be a lot easier.

Creating a window

Now that we have the core pieces in place, we can turn our attention to creating a window. The window in this example is going to display a couple of views (one at a time) and navigation will be achieved via some buttons.

This is what we’re aiming for;

WPF MVVM Structure Map Main Window

When a button is clicked, the corresponding view is displayed whilst displaying details about its data context.

Start by adding two interfaces;

public interface IMainWindow : IWindow
{
}

public interface IMainWindowViewModel : IWindowViewModel
{
}

No need to add additional properties at this stage, but you might want to add them going forward if you are planning on having multiple concrete classes that implement these interfaces, or if you are unit testing.

Next, head over to the MainWindow.xaml.cs file and make sure it implements the IMainWindow interface;

public partial class MainWindow : Window, IMainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

Now just add the MainWindowViewModel class, and add the following code;

public class MainWindowViewModel : BaseWindowViewModel, IMainWindowViewModel
{
    public MainWindowViewModel(IMainWindow window, IContainer container)
        : base(window, container)
    {
        ShowFirstChildCommand = new DelegateCommand<object>(OnShowFirstChild);
        ShowSecondChildCommand = new DelegateCommand<object>(OnShowSecondChild);
        ExitCommand = new DelegateCommand<object>(OnExit);
    }

    public DelegateCommand<object> ShowFirstChildCommand { get; set; }

    public DelegateCommand<object> ShowSecondChildCommand { get; set; }

    public DelegateCommand<object> ExitCommand { get; set; }

    private void OnExit(object obj)
    {
        Application.Current.Shutdown();
    }

    private void OnShowSecondChild(object obj)
    {
        ShowView<ISecondChildViewModel>();
    }

    private void OnShowFirstChild(object obj)
    {
        ShowView<IChildViewModel>();
    }
}

Note if you have not previously encountered the DelegateCommand, there are lots of implementations available online. You can download the version I have used here.

The constructor here is of critical importance to the whole concept. If you are using a refactoring tool such as ReSharper, please be sure to double check that the constructors first parameter is of type IMainWindow and not IWindow. ReSharper notices that you can use the more generic IWindow, as no properties from IMainWindow are used on the base class. Doing this, however, will result in StructureMap not knowing which type it actually needs to inject.

As we added the logic for displaying the actual view in our BaseWindowViewModel, we simply need to call ShowView() passing in the type of the view model we actually want to display. (The view that corresponds to the aforementioned view model).

Finally, open MainWindow.xaml and replace the existing Grid with the Grid below;

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
        
    <ContentControl Content="{Binding View}" 
                    Margin="10"/>
        
    <StackPanel Orientation="Horizontal"
                Grid.Row="1"
                VerticalAlignment="Center"
                HorizontalAlignment="Center">
            
        <Button Content="Show First Child"
                Command="{Binding ShowFirstChildCommand}"/>
            
        <Button Content="Show Second Child"
                Command="{Binding ShowSecondChildCommand}"/>
            
        <Button Content="Exit"
                Command="{Binding ExitCommand}"/>
            
    </StackPanel>
</Grid>

We will display our view (which is simply a user control) using a ContentControl. You can make this as elaborate as you like!

Creating a view

So far we have created our core classes, and created a window. Next we need to add a view to actually display within our window.

Add a new user control, call it ChildView.xaml and a matching IChildView.cs interface. Ensure that the user control implements the IChildView interface, and the IChildView interface implements IView… as shown below;

public interface IChildView : IView
{
}

public partial class ChildView : UserControl, IChildView
{
    public ChildView()
    {
        InitializeComponent();
    }
}

Next, create the ChildViewModel and IChildViewModel classes, as before ensuring that ChildViewModel implements IChildViewModel and IChildViewModel implements IView.

public interface IChildViewModel : IViewModel
{
}

public class ChildViewModel : BaseViewModel, IChildViewModel
{
    public ChildViewModel(IChildView view, IContainer container)
        : base(view, container)
    {
    }
}

As your ChildViewModel is going to inherit from BaseViewModel, as before you will be required to call the constructor of that class. Please ensure you take a second to double check that the view parameter is of type IChildView and not IView.

Now as an almost final step, go ahead and repeat this step. This time call it SecondChildView.

Tying it all together

First and foremost, we need to make sure that our IoC container knows about the windows and views that we have just added. Open up (or create) the bootstrapper that we created in the first part of this tutorial and add the following code.

Note that I have refactored out the lambda expression for simplicity.

public static class Bootstrapper
{
    public static void Initialise()
    {
        ObjectFactory.Initialize(OnInitialise);
    }

    private static void OnInitialise(IInitializationExpression x)
    {
        x.For<IMainWindow>().Singleton().Use<MainWindow>();
        x.For<IMainWindowViewModel>().Singleton().Use<MainWindowViewModel>();

        x.For<IChildView>().Use<ChildView>();
        x.For<IChildViewModel>().Use<ChildViewModel>();

        x.For<ISecondChildView>().Use<SecondChildView>();
        x.For<ISecondChildViewModel>().Use<SecondChildViewModel>();
    }
}

Notice in the above code, I have included the Singleton() method for the MainWindow and MainWindowViewModel types. This is because, if there are any subsequent requests for an instance of these types, the same instance will get served up every time.

Finally

All that is left is to retrieve an instance of MainWindow from the container and serve it up to the user. Don’t forget to initialise the bootstrapper in the application constructor.

public App()
{
    Bootstrapper.Initialise();
}

protected override void OnStartup(StartupEventArgs e)
{
    IMainWindowViewModel window = ObjectFactory.GetInstance<IMainWindowViewModel>();
    MainWindow = (MainWindow) window.Window;
    MainWindow.ShowDialog();
}

For the sake of completeness, I added a Resource Dictionary with the below style to set some sizing on the MainWindow buttons;

<Style TargetType="{x:Type Button}">
    <Setter Property="Width"
            Value="125" />
    <Setter Property="Height"
            Value="30" />
    <Setter Property="Margin"
            Value="5" />
</Style>

Summary

IoC containers provide a simple and elegant solution to doing dependency injection in a large WPF MVVM application. IoC containers are also responsible for managing the lifetime of our windows/views/view models. Using an IoC container also has a positive side effect of forcing you to structure your classes in a way that promotes unit testing.

Download source code