The Stochastic Game

Ramblings of General Geekery

Posts tagged with wpf

Making WPF controls double-clickable

A common UI pattern features the ability to double-click on a control to go in “edit” mode. So for example, you have a TextBlock that shows you the name of an object, and you can double-click it to change it into a TextBox where you can edit that name. At this point, it’s easy to hook up the MouseDoubleClick event, or some other mouse event, but that’s not very MVVM-like, is it?

Thankfully, WPF gives us the awesome attached dependency property API, which we already used for adding auto-complete to TextBoxes. The goal is to be able to write something like this:

<TextBlock Text="{Binding Name}" mi:ExtendedCommands.DoubleClickCommand="{Binding EditNameCommand}" mi:ExtendedCommands.DoubleClickCommandParameter="42" />

When the TextBlock would get double-clicked, the “EditNameCommandcommand object on the DataContext would get called with “42” as the parameter. This is super easy to do:

public static class ExtendedCommands
{
    public static readonly DependencyProperty DoubleClickCommandProperty;
    public static readonly DependencyProperty DoubleClickCommandParameterProperty;

    static ExtendedCommands()
    {
        DoubleClickCommandProperty = DependencyProperty.RegisterAttached("DoubleClickCommand", typeof(ICommand), typeof(ExtendedCommands), new UIPropertyMetadata(null, OnDoubleClickCommandPropertyChanged));
        DoubleClickCommandParameterProperty = DependencyProperty.RegisterAttached("DoubleClickCommandParameter", typeof(object), typeof(ExtendedCommands), new UIPropertyMetadata(null));
    }

    public static ICommand GetDoubleClickCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(DoubleClickCommandProperty);
    }

    public static void SetDoubleClickCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(DoubleClickCommandProperty, value);
    }

    public static object GetDoubleClickCommandParameter(DependencyObject obj)
    {
        return (object)obj.GetValue(DoubleClickCommandParameterProperty);
    }

    public static void SetDoubleClickCommandParameter(DependencyObject obj, object value)
    {
        obj.SetValue(DoubleClickCommandParameterProperty, value);
    }

    private static void OnDoubleClickCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var element = d as UIElement;
        if (element != null)
        {
            if (e.OldValue == null && e.NewValue != null)
            {
                element.MouseDown += new MouseButtonEventHandler(Control_MouseDown);
            }
            else if (e.OldValue != null && e.NewValue == null)
            {
                element.MouseDown -= new MouseButtonEventHandler(Control_MouseDown);
            }
        }
    }

    private static void Control_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ClickCount == 2)
        {
            var element = sender as UIElement;
            if (element != null)
            {
                var command = GetDoubleClickCommand(element);
                var parameter = GetDoubleClickCommandParameter(element);
                if (command != null && command.CanExecute(parameter))
                {
                    e.Handled = true;
                    command.Execute(parameter);
                }
            }
        }
    }
}

This code is pretty naive, but it gets the job done and illustrates quickly how to do it: just register 2 attached dependency properties in a new custom class, and whenever someone uses it on a UI element, start listening to the “MouseDown” event on that element and check against the “ClickCount” property to figure out if it’s a double-click. If it is indeed a double-click, just run the command that was specified for this control!

Obviously, you’ll need to handle error cases a bit better (like for instance if these properties are used on a non-UIElement), make it a bit better (for example register the MouseDoubleClick event instead of the MouseDown event if the target object is a Control), and other stuff like that. But, well, by now, you should know not to copy/paste code found on blogs without using your brain anyway.


Writing a custom Main() method for WPF applications

Creating a new WPF project in Visual Studio gives you the following pretty simple application markup and code:

<Application x:Class="WpfApplication2.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
</Application>

namespace WpfApplication2
{
    public partial class App : Application
    {
    }
}

Understanding how it really works, and how to supply your own custom Main() method, is just a search query away. You basically need to change the application’s build action from “Application Definition” to “Page”, create a constructor that calls “InitializeComponent”, and write your Main() by eventually calling one of the application’s “Run” method overloads.

wpf_app

namespace WpfApplication1
{
    public partial class App : Application
    {
        App()
        {
            InitializeComponent();
        }

        [STAThread]
        static void Main()
        {
            Window1 window = new Window1();
            App app = new App();
            app.Run(window);
        }
    }
}

Don’t forget, also, to remove the “StartupUri” from the App.xaml, otherwise another copy of window will show up (unless you get an error because the URI points to a non existing XAML resource).

What most articles won’t tell you, though (some of them actually getting it wrong), is that it’s important that you create the application before you create your first window. To illustrate this, let’s add an application resource to App.xaml:

<Application 
    x:Class="WpfApplication1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Red" />
        </Style>
    </Application.Resources>
</Application>

It’s a style that makes buttons red. Since it’s defined at application level, all buttons in all the windows should be red (except those that define their own local style override). For example, here’s the markup for my Window1:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Button>Is This Red?</Button>
    </Grid>
</Window>

We should see a window with a red button in it. But when I run the project, I get this:

not_red

Well… it’s not red.

The issue is that the window is created before the application. This means that when it queries the current application to get the globals resources, it finds nothing. What you need to do is simply create the application first:

[STAThread]
static void Main()
{
    App app = new App();
    Window1 window = new Window1();
    app.Run(window);
}

By simply switching those two lines, you get the expected result:

red

This drove me crazy for an hour or so – I thought there was something funky going on with my theme management code or something. Hopefully this will save someone some pain.


Fixing a bug can cause bugs

Microsoft apparently fixed something in .NET Framework 3.5 Service Pack 1 that previously didn't work, or somehow worked differently. As a result, Milkify will crash if used on a machine that doesn't have this service pack installed.

What you get is a XamlParseException that says that a ContentStringFormat property cannot be converted into a TemplateBindingExtension. This is because Milkify is using its own WPF skin where, among others, the check box control has a new custom template. This template is mainly a copy of the default one, courtesy of ShowMeTheTemplate, and looks like this:

<ControlTemplate x:Key="CheckBoxControlTemplate">
    <BulletDecorator>
        <BulletDecorator.Bullet>
            <Grid>
                <Border 
                  Width="18"
                  Height="18" 
                  CornerRadius="4"
                  BorderThickness="2"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  Background="{StaticResource MilkifyWhite}"
                  HorizontalAlignment="Center" 
                  VerticalAlignment="Center" />
                <Rectangle
                  Width="6"
                  Height="6"
                  Fill="Black" 
                  Name="RectCheck"
                  HorizontalAlignment="Center" 
                  VerticalAlignment="Center" />
            </Grid>
        </BulletDecorator.Bullet>
        <ContentPresenter 
          RecognizesAccessKey="True" 
          Content="{TemplateBinding ContentControl.Content}" 
          ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" 
          ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" 
          Margin="{TemplateBinding Control.Padding}" 
          HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" 
          VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" 
          SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
    </BulletDecorator>
    <ControlTemplate.Triggers>
        <Trigger Property="CheckBox.IsChecked" Value="False">
            <Setter TargetName="RectCheck" Property="Visibility" Value="Hidden" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Note how the ContentPresenter control defines ContentStringFormat so that it uses whatever string format has been defined on the actual, instanced, check box. Of course, my main programming machine has SP1 installed so it worked fine.

Anyway, for some reason, this works in .NET 3.5 SP1, but not on plain default .NET 3.5. I can't find much in the documentation about changes brought by SP1 that would explain why it behaves differently, and I don't think it's possible to tell ClickOnce that SP1 is a prerequisite to my application (you can only specify .NET 3.5 or not). I could remove that attribute completely, as I never specify it anyway, but it's not the ideal solution...


A variation on the auto-completing WPF TextBox

In this world of web 2.0 tagging madness, any good (or at least shiny enough) application needs a way to apply tags in a user-friendly way, namely with auto-completing text boxes. For example, the awesome Remember The Milk application has this:

image

What if we want a similar text box in WPF that would display a drop-down list of all the existing tags that match what the user is currently typing? The answer is, unfortunately, that we need to do it ourselves… but don’t be afraid, we’ll be playing around with cool things!

Auto-complete WPF text boxes have their fair share of articles on the web, but I find that Jason Kemp is the only one who wrote something interesting on the subject with his 4 part post (part 1, part 2, part 3, part 4). The main problem, however, is that all those articles deal with only auto-completing the full text of the text box, not each word as it is the case for a tag list. Let’s try to build our own solution, then and at the same time come up with a variation of Jason’s implementation.

The thing I liked about Jason’s solution was that he was using the Attached Property Pattern, which is one of the very powerful concepts that WPF and Silverlight offer. This pattern has already been discussed by Nikhil Kothari, John Gossman, and, err, BenCon (what’s his real name anyway?). What I didn’t like with Jason’s solution, though, was that in the end he was hijacking the control template of the text box to replace it with one that contained the popup to be used for showing the auto-complete suggestions. Since it’s common for designers to already replace a control template to re-look a control, I went with a different approach, which is to specify the “external” popup you want to use.

It goes like this:

    <Grid
        Margin=”10”>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=”Auto” />
            <ColumnDefinition Width=”*” />
        </Grid.ColumnDefinitions>
        <TextBlock>Tags: </TextBlock>
        <TextBox
            Grid.Column=”1”
            Name=”TextTags”
             local:TextBoxAutoComplete.WordAutoCompleteSource=”{Binding Source={StaticResource Tags}}”
            local:TextBoxAutoComplete.WordAutoCompletePopup=”{Binding ElementName=PopupTags}” />
        <Popup
            Name=”PopupTags”
            IsOpen=”False”
            Placement=”Bottom”
            PlacementTarget=”{Binding ElementName=TextTags}”>
            <Grid>
                <ListBox Name=”PART_WordsHost” />
            </Grid>
        </Popup>
    </Grid>
In this example, we have a text box called “TextTags” which has 2 attached properties: one that defines the source for all the suggestions, and one that defines the popup that will show the matching suggestions. The tricky part is that you need to know where to “feed” those matching suggestions. There’s a good chance there’s going to be some kind of list control in the popup where the suggestions should be inserted, but how to get to it?

It’s somewhat of a convention in WPF that if you need some “handshaking” between the look and the logic of a control, you should use named controls with a “PART_” prefix. This is what happens here, with the ListBox being called “PART_WordsHost“. This decouples the logic from the appearance, letting you arrange the popup as you want, or even use a ComboBox or a ListView instead of a ListBox.

You can read more about this “PART_” business in books like “WPF Unleashed” or “Programming WPF” (I haven’t found a good article on the web yet). Also, note that this convention is usually used between the logic of a control and its own control template, which is not exactly the case here, but it works all the same.

Now let’s look at the interesting bits in the code. This is implemented in a static class called “TextBoxAutoComplete“.

First, we need to register the attached dependency properties.

public static readonly DependencyProperty WordAutoCompleteSourceProperty;
public static readonly DependencyProperty WordAutoCompleteSeparatorsProperty;
public static readonly DependencyProperty WordAutoCompletePopupProperty;
static TextBoxAutoComplete()
{
      var metadata = new FrameworkPropertyMetadata(OnWordAutoCompleteSourceChanged);
      WordAutoCompleteSourceProperty = DependencyProperty.RegisterAttached(“WordAutoCompleteSource”, typeof(IEnumerable), typeof(TextBoxAutoComplete), metadata);

  metadata = <span style="color: blue;">new </span><span style="color: #2b91af;">FrameworkPropertyMetadata</span>(<span style="color: #a31515;">",;"</span>);
  WordAutoCompleteSeparatorsProperty = <span style="color: #2b91af;">DependencyProperty</span>.RegisterAttached(<span style="color: #a31515;">"WordAutoCompleteSeparators"</span>, <span style="color: blue;">typeof</span>(<span style="color: blue;">string</span>), <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">TextBoxAutoComplete</span>), metadata);

  metadata = <span style="color: blue;">new </span><span style="color: #2b91af;">FrameworkPropertyMetadata</span>(OnWordAutoCompletePopupChanged);
  WordAutoCompletePopupProperty = <span style="color: #2b91af;">DependencyProperty</span>.RegisterAttached(<span style="color: #a31515;">"WordAutoCompletePopup"</span>, <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">Popup</span>), <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">TextBoxAutoComplete</span>), metadata);

}

public static void SetWordAutoCompleteSource(TextBox element, IEnumerable value)
{
    element.SetValue(WordAutoCompleteSourceProperty, value);
}

public static IEnumerable GetWordAutoCompleteSource(TextBox element) { return (IEnumerable)element.GetValue(WordAutoCompleteSourceProperty); }

public static void SetWordAutoCompleteSeparators(TextBox element, string value) { element.SetValue(WordAutoCompleteSeparatorsProperty, value); }

public static string GetWordAutoCompleteSeparators(TextBox element) { return (string)element.GetValue(WordAutoCompleteSeparatorsProperty); }

public static void SetWordAutoCompletePopup(TextBox element, Popup value) { element.SetValue(WordAutoCompletePopupProperty, value); }

public static Popup GetWordAutoCompletePopup(TextBox element) { return (Popup)element.GetValue(WordAutoCompletePopupProperty); }

You can check MSDN for some explanation on this. Don’t forget the static getters and setters, because without them, the XAML syntax won’t work.

Here are the “dependency property changed” callbacks:

private static void OnWordAutoCompleteSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    TextBox textBox = (TextBox)d;
    SetWordsHostSourceAndHookupEvents(textBox, (IEnumerable)e.NewValue, GetWordAutoCompletePopup(textBox));
}

private static void OnWordAutoCompletePopupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBox textBox = (TextBox)d; SetWordsHostSourceAndHookupEvents(textBox, GetWordAutoCompleteSource(textBox), (Popup)e.NewValue); }

private static void SetWordsHostSourceAndHookupEvents(TextBox textBox, IEnumerable source, Popup popup) { if (source != null && popup != null) { //TODO: make sure we do this only this once, in case for some reason somebody re-sets one of the attached properties. textBox.PreviewKeyDown += new KeyEventHandler(TextBox_PreviewKeyDown); textBox.SelectionChanged += new RoutedEventHandler(TextBox_SelectionChanged); textBox.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);

    <span style="color: #2b91af;">Selector </span>wordsHost = popup.FindName(<span style="color: #a31515;">"PART_WordsHost"</span>) <span style="color: blue;">as </span><span style="color: #2b91af;">Selector</span>;
    <span style="color: blue;">if </span>(wordsHost == <span style="color: blue;">null</span>)
        <span style="color: blue;">throw new </span><span style="color: #2b91af;">InvalidOperationException</span>(<span style="color: #a31515;">"Can't find the PART_WordsHost element in the auto-complete popup control."</span>);
    wordsHost.IsSynchronizedWithCurrentItem = <span style="color: blue;">true</span>;
    wordsHost.ItemsSource = source;
    textBox.SetValue(WordAutoCompleteWordsHostPropertyKey, wordsHost);
}

}

What this code does is that whenever a text box has been assigned both a source and a popup for the auto-complete feature, we hook up some event handlers on the text box to listen for user input. We also look for the selector control that will host the auto-complete suggestions (in our case, the ListBox), and set its data source to be our own source for those suggestions.

Obviously, this code needs some more work, like making sure we’re not re-registering the same events twice (which shouldn’t happen if you only set this in XAML). Also, as I mentioned earlier, we’re only looking for a control named “PART_WordsHost“, and throw an exception if we don’t find it, or if it’s not a selector control. We could be a bit nicer and try to explore the popup’s tree, looking for some selector control, but this exception will be raised the first time the user tests his code anyway, and is pretty self-explanatory, so I think it’s not a big deal for now.

Now that we’ve hooked up some event handlers to the text box, we can start doing the work. I won’t post the whole code here, as it’s mostly boring logic code that figures out what the user is doing and shows or hides the popup accordingly. However, there’s a few interesting things to discuss about this code.

First, we have a dependency property set up that contains the separator characters we should use to split and parse the text box’s text. Since our main use case is tags, the default separators are “,” and “;”. Use the TextBox‘s CaretIndex, SelectionStart and SelectionLength to figure out where the user is currently typing things.

Second, we can take advantage of the filtering features of WPF‘s data binding (more specifically the ICollectionView). When we have figured out what tag name the user is currently typing, we can set the filtering delegate on the words host items collection:

private static void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = (TextBox)sender;
    Popup popup = GetWordAutoCompletePopup(textBox);
    string currentWord;// (SKIPPED CODE: get the currently typed word)
    if (currentWord.Length > 0)
    {
        // Filter all the auto-complete suggestions with what the user is currently typing.
        Selector wordsHost = (Selector)textBox.GetValue(WordAutoCompleteWordsHostProperty);
        wordsHost.Items.Filter = o => GetTextSearchText(wordsHost, o).StartsWith(currentWord, StringComparison.CurrentCultureIgnoreCase);
        // (MORE SKIPPED CODE) 
    }
    // (MORE SKIPPED CODE)
}
This leads us to another interesting point… see that “GetTextSearchText” method? It’s supposed to return the string representation of any item in the auto-complete suggestion list. Because we’re doing all this to handle tags, we know each item will actually be a string, so it’s easy. But it’s not so easy if you’re handling custom objects, and you want some kind of auto-complete text box for writing lists of such objects.

In this case, you would probably get the TypeConverter of each object and use that to get a string representation. After all, you need some bi-directional conversion in order to later parse the list the user typed in the text box! The TypeConverter is well suited to this task, but the whole thing made me look at the TextSearch class.

TextSearch is a class that defines attached properties that allow you to control the text representation of objects in search and auto-complete scenarios. The typical example of this is for editable ComboBoxes, where the user can type something in the editable part, and the system automatically pre-selects the correct entry in the ComboBox‘s drop-down menu (actually, simple auto-complete text boxes can be implemented with a ComboBox and a few lines of XAML!). In this case, each entry in the ComboBox can have a TextSearch attached property that provides the string they can be matched against. Looking at the ComboBox‘s code shows that it calls methods on TextSearch like “FindMatchingString(Object)” or “GetPrimaryText(Object)”. Those methods are nice because they handle all kinds of other cases, like when the object is an XmlNode, or is a FrameworkElement. The problem is that those methods are internal, so we can’t use them! Some people don’t want to rewrite that logic code and, hoping Microsoft will one day make those methods public, use awful ways in the meantime to work around the problem. I can’t really blame them, especially when they feel bad already.

Luckily, in our case, we’re only manipulating strings so all is fine, but you may want to rewrite that “GetTextSearchText” method to your liking.

The last point I wanted to discuss is that this kind of attached behaviour sometimes needs to stores some custom data on its target. In our case, we may want to “cache” the control that acts as the words host because we don’t want to look for “PART_WordsHost” every time the user types something. If you look at that last snippet of code, you can see I stored a reference to that control in a dependency property called “WordAutoCompleteWordsHostProperty“.

This dependency property is a read-only attached property, and those are pretty useful to store things only you should be able to set. I use them here to cache the words host control, but also to set a variable that tells us whether a selection change in the text box was caused by text input, or caused by the user navigating left and right (using the left and right keys, or clicking on the text with the mouse… this has some effect on whether to show or hide the popup).

Well, I believe that sums it up. The code as an attachment to this post, with a demo application that uses all the names of the “Key” enumeration as the source for auto-complete suggestions. See the screenshot below:

image

Note that this demo code won’t be maintained. To get my latest version of it, you can download the source code of Milkify and look for TextBoxAutoComplete.cs. For example, I plan to try and get the popup to show up just below the currently typed tag name, instead of aligned at the bottom left of the text box… but that’s all details. You have everything you need to write your own!

TextBoxAutoCompleteDemo.zip (10.78 kb)


WPF application patterns continued: convention over configuration

In my previous post on WPF application patterns, I went over a few of the most common patterns available, and gave some pointers on how to implement them in WPF. I mentioned how you could use a dependency injection framework to decouple the implementation of your views and controllers from each other. However, the problem when using dependency injection out of the box is that you need an interface to bind to.

Soon, you end up with this:

Lots of interfaces

 

And this kind of initialization code (using Ninject1, but it's straightforward to understand):

class ApplicationModule : StandardModule
{
public override void Load()
{
Bind<IAccountController>().To<AccountController>();
Bind<IAddProductController>().To<AddProductController>();
Bind<ICategoryController>().To<CategoryController>();
Bind<ICategoryListController>().To<CategoryListController>();
Bind<IEditProductController>().To<EditProductController>();
Bind<IMainWindowController>().To<MainWindowController>();
Bind<IProductController>().To<ProductController>();
Bind<IProductListController>().To<ProductListController>();
Bind<ISettingsController>().To<SettingsController>();
Bind<ISummaryController>().To<SummaryController>();
}
}

You're flooded with interfaces that will be, most of the time, empty (because, remember, you're using WPF features such as data binding and commanding to control your view, thus removing the need for much specific wiring code beside what will be in the base IView and IController interfaces). Remember that the example above only has 10 views in total, which means it's a pretty damn small application, and you have to double the initialization code because I just wrote it for the controllers (you need the same thing for the views).

It's tedious, and quite repetitive, and you know how lazy developers are.

Ruby On Rails made popular the "convention over configuration" paradigm, which previously didn't have much spotlight. We can get on that bandwagon to remove some of our work.

More specifically, because we're nice and obedient developers, we know that our controllers and views will be called "FooView" and "BarController". So instead of getting a view or a controller based on its interface, we could get it based on its "name" (where the name here is "Foo" or "Bar").

We're therefore trading this code:

class AccountController : IAccountController
{
public void Execute()
{
IAccountView view = KernelContainer.Kernel.Get<IAccountView>();
}
}
For this code:
class AccountController : IAccountController
{
public void Execute()
{
IAccountView view = (IAccountView)viewFactory.Create("Account");
}
}

By the way, notice how most MVC/MVP frameworks for web applications already work like this.

Anyway, this is not too bad, given that we're doing this so that we can remove most of our interfaces, and change the initialization code to something much simpler and scalable. In our case, the initialization code could be as follows... First, bind all classes called "SomethingController" or "SomethingView" to themselves:

class ApplicationModule : StandardModule
{
public override void Load()
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
if (typeof(IView).IsAssignableFrom(type) && type.Name.EndsWith("View"))
Bind(type).ToSelf().Using<TransientBehavior>();
}
}
}
}

Then, implement the IViewFactory by building the full type name of the requested view, and then asking the IOC container to build it for you (as opposed to using Activator.CreateInstance, so that any dependencies are correctly injected):

class ViewFactory : IViewFactory
{
#region IViewFactory Members
public IView Create(string viewName)
{
Type viewType = GetViewType(viewName);
IView view = (IView)KernelContainer.Kernel.Get(viewType);
return view;
}
#endregion
}

This code will stay pretty much the same as the application grows, unlike the other code, and you can switch modules for your unit tests. Of course, you may want to have a more solid test to know what type should be considered a view, or have better control over which assemblies are reflected, etc. This is just example code. Remember also that this is only executed once at startup, so unless you have severe startup performance requirements, the cost shouldn't be noticeable. Otherwise, you could always generate the code during build and compile that instead.

Now, I know, I know, my original code is not dependency injection, because I'm fetching the IAccountView myself from the IOC container (so this is really a Service Locator pattern). You would preferably have this instead:

class AccountController : IAccountController
{
private IAccountView mView;
public AccountController(IAccountView view)
{
mView = view;
}
public void Execute()
{
// Do something with the view.
}
}

That is, get the view injected into the controller.

However, you can't do that half the time. The goal of a controller is not only to process user actions on a view, it's also to choose what view to show in the first place (which means you don't always have a 1 on 1 relationship between controllers and views). You may therefore have some logic code in there that, depending on the context (is the user logged in, does he belong to the correct group, has he been banned, etc.), will show different views (redirect to the login view, display the regular user or administrator account view, display an error message, etc.). You don't want all possible views injected in your controller, because any of those views could have a costly constructor itself. So you really need to fetch the view yourself programmatically.

What you would get injected, on the other hand, is the view factory that I use in my modified code:

class AccountController : IAccountController
{
public AccountController(IViewFactory viewFactory)
{
IAccountView view = (IAccountView)viewFactory.Create("Account");
}
}

And as I mentioned earlier, it's probable that your IAccountView is empty, so you can actually get away with just using IView, thus removing the cast.

Now we have a nice way to manage our views and controllers, and how to make them relate to each other. In future posts, we'll look at other implementation details of WPF applications, such as giving controllers some context and handling user actions.

1 Because it's a cool IOC framework, with a super cool name and logo!