Switching DataTemplates dynamically in WPF

January 26th, 2009

I spent a couple of days last week writing a (very) simple Sudoku solver in WPF. For the most part, everything I wanted to do was ridiculously easy to achieve with WPF. However, there was one point that took me an hour or two of research to figure out: switching DataTemplates dynamically.

To draw my Sudoku board, I data bind to some model-objects that describe the board. Each cell on the board has a value (a nullable int), and a list of values that could possibly go in that cell. The effect I wanted to achieve was to show the value for a cell if it’s not null, and show a grid of possible values if not yet determined:

Example of Desired Dynamic DataTemplate Effect

I finally found the answer in a comment by Andy Kutruff on a post asking a very similar question to mine . There’s a minor skirmish in the comments about whether or not Andy’s solution is injecting business logic into the presentation layer, but I feel that his solution is the correct one for this application because the two templates are purely a UI concern, and not related to the functioning of the model.

The basic idea is to use a DataTemplate containing a single ContentPresenter as a selector. The ContentPresenter has a ContentTemplate set on it that becomes the default template. Data triggers on the template are then used to switch between the various sub-templates for the ContentPresenter. The following are reformatted excerpts from the XAML code for my sudoku solver. To see the full source code for the project, look at the code page. Please excuse the lack of syntax highlighting for XAML; I need to figure out something for that.

To start, we need to make a DataTemplate that is used by the control in question. This template simply contains a ContentControl whose contents will be swapped out based on data.

<DataTemplate x:Key="CellTemplate">
    <ContentControl 
        ContentTemplate="{StaticResource CellSelectorTemplate}" 
        Content="{Binding}" />
</DataTemplate>

Finally, we create the template that does the selecting of sub-templates. This works by using data triggers to change the ContentPresenter’s ContentTemplate.

<DataTemplate x:Key="CellSelectorTemplate">
    <ContentPresenter x:Name="Presenter"
        ContentTemplate="{StaticResource CellWithValueTemplate}"
        Content="{TemplateBinding Content}" />
 
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Value}" Value="{x:Null}">
            <Setter TargetName="Presenter"
                Property="ContentTemplate"
                Value="{StaticResource CellWithoutValueTemplate}" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

After that, it’s just creating the templates for each of the states needed. The data trigger switches between the templates depending on the data, and the templates do their magic.

Open-Instance Delegates for flexible event bindings

January 15th, 2009

In my continued work on the XNA project, I recently worked on an input system that supported key bindings. What I wanted was to be able to bind a key / button to a handler method in such a way that I could call the binding on whichever object currently had focus for input. C++’s pointer-to-member-function syntax instantly sprang to mind, so I poked around in C++/CLI’s documentation to see how they implemented it in .NET.

The answer is open-instance delegates (or unbound delegates as they’re called in C++/CLI). Though C# has no support in its syntax for open-instance delegates, you can still create and use them.

The trick is to create a delegate type that takes the same parameters as the method you want to bind to, but includes an extra parameter for the instance at the beginning of the parameter list. Given this class with a single method:

class InputSink
{
	public void OnExitButtonPressed(object sender, EventArgs args)
	{
		// ...
	}
}

The delegate and code to create it would look like this:

delegate void Handler(InputSink @this, object sender, EventArgs args);
 
var method = typeof(InputSink).GetMethod("OnExitButtonPressed");
return (Handler)Delegate.CreateDelegate(typeof(Handler), null, method);

The delegate is now an open-instance delegate that can be used on any object of or derived from InputSink. From there, it’s easy to throw the new delegates into a dictionary using the XNA Buttons (such as Buttons.Start, Buttons.A, etc.) as a key and easily look up bindings at runtime. To use the delegate you just pass an instance as the first parameter like so:

var inputSink = new InputSink();
Handler someHandler = GetHandler(); // assume this is the code block above
 
someHandler(inputSink, sender, EventArgs.Empty);

NUnit and XNA on Windows x64

November 17th, 2008

I’ve been working on a project using XNA recently, and since I’ve been learning TDD and unit testing I wanted to use NUnit. However, whenever I tried to load the test assembly in the test runner, I’d get the following (rather unhelpful) error:

Could not load file or assembly 'Spladug.Project.Tests' or one of 
its dependencies. The system cannot find the file specified.

After poking around for a while, I discovered that my problem stemmed from being on Windows x64. XNA’s libraries are 32-bit only, which means that despite being .NET, applications (and class libraries) built on XNA are always 32-bit. As described in a post about testing 32-bit applications on Windows x64, you have to configure NUnit to run in 32-bit mode as well to be able to load the test assembly.

To do this, simply run the following command in a console with sufficient permissions and with filenames tweaked as necessary:

C:\>corflags "C:\Program Files (x86)\NUnit 2.5\net-2.0\nunit.exe" /32BIT+

corflags is a utility that comes with the .NET Framework SDK. See the documentation for .NET Framework Tools for more details.