DataTemplates are essential tools provided by WPF that allow us to describe the visual structure of  any type of object.

When declaring a DataTemplate, one typically is doing so with the intention of targeting a specific type (or valid subtype) of object. This is done by setting the DataType property of the DataTemplate to the Type of object we’re targeting.

Because the data templating system matches templates not only against instances of the specified type, but against derived types in the specified type’s hierarchy, DataTemplates are an easy way to visually shape large swathes of your own types of interest…

…As Long as the DataType Isn’t an Interface

WPF’s data templating system does not support the explicit targeting of interface types. If you mean to target a “base type” from which many other types descend, then you will have to make do with a standard object type; an abstract class is the closest thing to an interface that we’re allowed to target with DataTemplates.

This may be received by some as saddening news, as many legitimate object hierarchies exist out there whose members only share a specific interface in common. This limitation of WPF would then force an individual working with such an object hierarchy to create a base type (either to implement or wholly replace the interface) solely to get WPF to play nice with their model.

No one likes to be made to do something seemingly arbitrary and without true purpose; fortunately for us, there is a way we can add interface support to DataTemplates. Before we get into that, however, let’s think as to why WPF’s data templating system lacks support for interfaces.

The lack of interface support was the result of a call made by the early developers of the framework, and I believe it was the right one. When designing a frameworks like the greater .NET Framework or WPF, one must design with the intent of producing a framework which behaves in an expected and stable manner. Adding support for a typical object’s type hierarchy is a straight forward objective, as the type hierarchy will consist of a very well defined order of types that can easily be traversed.

There are too many potential caveats when one starts talking about adding support for interfaces, mainly due to the multiple inheritance angle of interfaces; you can easily get into situations where an object implements two interfaces which are also targeted by two separate DataTemplates.

Luckily for us, we aren’t designing a framework intended for mass consumption, so we can implement support with full awareness of what not to do in conjunction with its use.

Adding Interface Support with a DataTemplateSelector

By creating a DataTemplateSelector and using it, we can effectively define data templates which target interfaces as opposed to only standard objects.

Most of the time when we create a DataTemplateSelector, we design it so it can be equipped with a finite number of different DataTemplates to be doled out at run time based on some business-specific logic. This selector is a bit different, as this selector is meant to offer an alternative way of selecting templates in general; thus, this selector must use all resources found in the tree of the container as well as in the current application’s resources as its source for DataTemplates.

This sort of activity should certainly seem to you to be one that carries potentially negative consequences for performance, as combing through the entire set of loaded resources can indeed be an intensive task. In order to alleviate these concerns, the wisest course of action would be to attempt to use (as much as possible) WPF’s own faculties for searching through all relevant resource dictionaries.

There are a number of methods that allow for searching for specific resources across all, however these are internal. But we don’t need to worry about that, because, like many things in life, simplicity is the key, and we can make use of a very simple and familiar method to achieve our objectives: FindResource. Many people are probably used to just using this method to find a resource by its literal string name; instead of the literal name, we’ll be searching using a specific type of ResourceKey.

Below is the code for the template selector:

/// <summary>
/// Provides a data template selector which honors data templates targeting interfaces implemented by the
/// data context.
/// </summary>
public sealed class InterfaceTemplateSelector : DataTemplateSelector
{
    /// <inheritdoc/>
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement containerElement = container as FrameworkElement;

        if (null == item || null == containerElement)
            return base.SelectTemplate(item, container);

        Type itemType = item.GetType();

        IEnumerable<Type> dataTypes
            = Enumerable.Repeat(itemType, 1).Concat(itemType.GetInterfaces());

        DataTemplate template
            = dataTypes.Select(t => new DataTemplateKey(t))
                .Select(containerElement.TryFindResource)
                .OfType<DataTemplate>()
                .FirstOrDefault();

        return template ?? base.SelectTemplate(item, container);
    }
}

InterfaceTemplateSelector.cs

This will return the first DataTemplate encountered which targets one of the interfaces implemented by the item, with greater precedence given to templates that specifically target the concrete type of the item. If no templates are found, then the base selection logic will fire. The base selection logic should expand the search to include the rest of the object types in the item’s type hierarchy. Thus, the templates based on their targeted type returned, in order of precedence, is:

  1. Templates targeting the item’s specific type
  2. Templates targeting an interface implemented by the item
  3. Templates targeting other object types found in the item’s type hierarchy.

#2 and #3 may seem a bit unnatural, and that’s because they are. A superior solution would give greater precedence to object types found in the item’s type hierarchy if they too implement the same interfaces. If they do not, and the implementation of the interface is done somewhere in the hierarchy lower than the position of a given ancestor, then the template targeting that interface would take precedence.

Such efforts are largely unnecessary, however, as common sense would dictate that one should only use this selector isn’t meant to data template selection in its entirety; it should be used scenarios where interface is king.

 

Microsoft has recently released a preview version of their new Office 2013 product which adds support for their new touch screen platforms (while maintaining support for PCs).

Looks like anyone can grab a copy and try it out for themselves, if interested you can head on over to the official site. If you have a MSDN account, you can also find a download on there.

I decided to grab it myself to check out a few things, mainly:

  1. What the new interface looks like, and…
  2. If there were any breaking changes in their add-in hosting model and mechanisms.

Although I tend to only write  (hopefully) deep and useful software development articles, let’s make an exception to that pattern today with a little exposé on the new Outlook.

Inbox and Calendar: The New Look (Warning: High Contrast)…

As soon as Outlook loaded I somewhat felt like I was being assaulted with “white”. Man, there is a lot of white color on the new interface.

Any and all shades of color have been nuked and obliterated from the UI. Instead, we have some very solid colors, with blue being a prominent part of the new palette.

Outlook 2013's Ribbon

Outlook 2013's Ribbon

Yes, very white.

I actually like user interfaces with white backgrounds, however, the interfaces I make which use that color tend to be a bit simpler than the one Outlook uses. My immediate reaction to it is not a favorable one.

The inbox panel is also very white:

Outlook 2013's Inbox Panel

Outlook 2013's Inbox Panel

Sorry for the censorship. Regardless, I’d opt to have a bit more of a delineation drawn between the individual items; moreso here than in other places even.

The Navigation Pane has been updated as well; it is now on the very bottom, and it is now composed of words rather than pictures:

Outlook 2013's Navigation Bar

Outlook 2013's Navigation Bar

I do believe I like the calendar very much, however. Here’s a screenshot of everything with the calendar showing:

Outlook 2013's Calendar

Outlook 2013's Calendar

Very short summary: I think I like the look, but I can’t help but feel that the change to the interface initially invokes an overall feeling of shock when looking at it. A bit too white in areas, too; the blue bar at the bottom is kind of bugging me as well.

 Add-ins and Whatnot

All of my add-ins targeting previous version of Outlook loaded successful in Outlook 2013. Looks like they preserved the plugin model they had going before, although I’m sure some unannounced changes will surface eventually, as they always do with new releases of Outlook.

In the future, I will be writing articles covering any new development technologies I run across in Outlook 2013.

 

WPF affords developers the opportunity to create layouts that coincide greatly with how the look and behavior of a particular user interface was envisioned to be. The tricky part is, as always, knowing how to use the tools we’re given.

One common layout-related issue people run into is the layout of items displayed within an ItemsControl, specifically the space between the items. More often than not, items will not be displayed in a manner regarded as acceptable by the developer; some tweaking and customization is required to get what we want.

Sometimes we have very particular requirements set in how we want our final layouts to appear and behave. In this article, we’re going to look at an example featuring an ItemsControl, its children, and how we might be able to space it out so that it satisfies our goals.

I. The Scenario

In our application, we have the need to display a collection of customizable input fields at the bottom of our form. These input fields are defined by administrators managing the product, thus we are unaware of exactly how many of these input fields are going to end up appearing on our form.

Each input field consists of a self-describing label as well as an actual input element, such as a text box or a combo box. Although each field features two elements (label and input), it is collectively powered by a single piece of data. The following is an example of one of our input fields:

Example of a Displayed InputItem

Example of a Displayed InputItem

Appearances are important, so we have a number of requirements on how collections of these fields are laid out:

  1. Fields are laid out horizontally, but must wrap if they cannot fit on the screen
  2. Each field is spaced apart from the next and previous field in the collection by an amount dependent on the width of the window or root container. Fields should neither be too close nor too far apart, regardless of window size.
  3. Wrapped fields are aligned perfectly underneath their counterparts located above and/or below them (resulting in a grid-like layout).

If the window is large enough, the input fields should be laid out in only a single row, with proper spacing between each one, like so:

A Single Row of Input Fields.

A Single Row of Input Fields.

Notice how there is ample spacing between each item. Let’s see what we get when we constraint the width to the width shown above and add a few more fields:

Multiple Rows of Input Fields

Multiple Rows of Input Fields

See how everything is lined up in a grid-like fashion.

Now, we have no idea how many fields the customer will be adding, and we also don’t know how large their screens will be. So, our layout needs to be fluid in its shape in order to accommodate all these different possibilities. If we decrease the width of our window, we’ll have the following:

Multiple Rows of Input Items with Less Width Available

Multiple Rows of Input Items with Less Width Available

You’ll see how the number of columns shifted down to two. If you’re screen is wide enough, then you would get something like:

Multiple Rows of Input Items with Lots of Width Available

Multiple Rows of Input Items with Lots of Width Available

II. Pick Yer Poison (err, Panel)

Now that we have a good picture of what we want our layout to look like, we can proceed to choosing the particular panel to employ in our ItemControl‘s ItemsPanelTemplate.

Typically, when one wishes to achieve a “grid-like” layout, one would do well to make use of a Grid or UniformGrid. Certainly a UniformGrid might seem appropriate here, as is the typical choice when the goal is to evenly lay out items in a grid-like, evenly distributed fashion within an ItemsControl.

Unfortunately, that will not work for us here. We’re using WPF because it is dynamic dammit, and UniformGrid is a highly restrictive layout panel in that it requires the specification of the number of columns within its declaration.

Nay, a UniformGrid will not do! We need to adjust the number of columns based on the available width; in other words, we need to wrap appropriately. Therefore, the natural choice for our panel is the WrapPanel.

While the WrapPanel achieves our requirement of adjustment based on available width, it does not space out items and does not lay them out in a fashion that could be described anything close to “grid-like”. If we simply plop in a WrapPanel within our ItemsPanelTemplate, we’re going to get something like the following:

Ugly Input Field Layout

Ugly Input Field Layout

Dear Lord, that is hideous. But things are never pretty by accident (except organic life forms), and we are well on our way in getting the layout we want by making the WrapPanel our weapon of choice.

To start on the process of beautifying this pathetic creature, let’s talk briefly about the UI design behind each of the input fields.

III. Input Fields Be Stylin’

I’m going to leave up the exact design of these simple input fields as an exercise for the reader, for the most part.

In brief, the data powering each input field is responsible for indicating the type of exact input control which should be rendered, be it via a Boolean value or what have you.

A single Style is used which targets controls of the…Control variety. The name we’ll be using for this particular style is InputControlStyle. Based on our little indicator, it is wired to select the appropriate template. The various templates consists of a text block to display the descriptive text of the field, as well as a declaration of the particular type of input control which distinguishes it from the others.

So, while the actual design of the input field is arbitrary as far as we’re concerned, part of the solution for making our layout nice and pretty lies in their design. As was just witnessed in the previous section, using a WrapPanel gives us wrapping, but no grid alignment.

Luckily for us, children need not be wholly dependent on a common ancestral container in order to be collectively aligned in a grid-like manner. Instead, we can share size information between each of these fields so that we end up with just that.

We can share size information by taking advantage of the SharedSizeGroup feature made available by the DefinitionBase class.

Now, you’ve probably never heard of the DefinitionBase class before, and that’s just swell, but you’ve certainly toyed with its derivatives (e.g. ColumnDefinition, RowDefinition). These derivatives, however, only apply to Grid controls, thus we are going to need Grid controls somewhere in our setup. Going back to the template for each of the different kinds of input fields, we mentioned that each template will consists of two items. However, some sort of layout container will be needed to band the two elements together, and that’s where our Grid declarations will go.

In order to maintain our typical level of high standards and cleanliness, we’ll want to create a Style for these Grid controls so that all templates which provide a different type of input element can join the party. Assuming our magic Grid style is named InputGridStyle, an example template (one featuring the use of a text box) is as follows:

<ControlTemplate x:Key="TextBoxInputTemplate">
    <Grid Style="{DynamicResource InputGridStyle}">
          <TextBlock Style="{DynamicResource InputTextBlockStyle}"
                     Grid.Column="0"
                     />
          <TextBox Style="{DynamicResource InputTextBoxStyle}"
                   Grid.Column="1"
                   />
    </Grid>
</ControlTemplate>

Template for Combo Box Input Fields

The styles being applied to the text block and box are arbitrary and should obviously satisfy any aesthetic and data binding objectives.

Any other template need only adhere to using a Grid control with the above style applied in order to appear correctly in our ItemsControl.

Now that you have an unbelievable understanding of how these input templates are organized and work, we’ll move on to the real magic show: the common Grid style in use by each of these templates.

As was mentioned previously, we need to tap into the SharedSizeGroup feature in order to achieve our objectives. The SharedSizeGroup property accepts a string describing the name of the group that the particular Grid should enter into. All Grid controls entered into the same group will then share size information with each other as well as That Which Contains Them (a bit Lovecraftian, I know).

But wait, didn’t we say that the SharedSizeGroup property belongs to DefinitionBase-based class, like ColumnDefinition or RowDefinition? Some of you may see this alone as being a problem in our quest to create style defining the shared size group membership information.

For those of you not in the fold: styling ColumnDefinition/RowDefinition is problematic because, well…you can’t style the Grid control’s ColumnDefinitions and RowDefinitions properties. That’s because neither of those properties are actually dependency properties. What’s more, the Grid control is not actually a control, in that it does not derive from Control, it derives from Panel, which itself derives directly from FrameworkElement. This means that making use of a ControlTemplate is not a possibility either.

Well (maybe unfortunately for you), in my solution to our layout problem, I do actually style the grid’s column definitions, but I do so by making use of an attached property that lets me do so. Creating such an attached property is outside the scope of this article, but you should be able to find plenty of examples online that will guide you in that task. If all else fails, just drop the style altogether and simply re-declare duplicate ColumnDefinitions in all of your templates, and pray no one ever makes a spelling error in the name.

Here is the style of our Grid common to all the templates (the “lib” namespace is a fictitiously named one that represents a custom UI framework where I keep such things as the attached properties we’re going to be using):

<Style x:Key="InputGridStyle" TargetType="{x:Type Grid}">
    <Setter Property="Margin" Value="0,0,0,5"/>
    <Setter Property="lib:GridProperties.ColumnDefinitions">
        <Setter.Value>
            <lib:ColumnDefinitionCollection>
                <ColumnDefinition SharedSizeGroup="InputTextGroup"/>
                <ColumnDefinition SharedSizeGroup="InputValueGroup"/>
            </lib:ColumnDefinitionCollection>
        </Setter.Value>
    </Setter>
</Style>

Style Used by Input Field Grids

Note: Although WPF ships with a ColumnDefinitionCollection type (which is where ColumnDefinition instances get stored), and even though it is public, it has no default constructor, thus we cannot make use of it in an XAML declaration. You’ll need to make one your self, all it needs to do is implement an existing collection class targeting the ColumnDefinition type for its items (ObservableCollection<ColumnDefinition>or whatnot).

That takes care of our input item styles.

IV. Turn on Size Sharing

Now that our items are set up to share size information, we need to enable size sharing on the containing WrapPanel itself. We can do this simply by setting the Grid.IsSharedSizeScope attached property to true in the WrapPanel declaration.

Taking everything we’ve done, we should have the following declaration for our ItemsControl this far:

<ItemsControl ItemsSource="{Binding YourData, UpdateSourceTrigger=PropertyChanged}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Grid.IsSharedSizeScope="True"
                       Orientation="Horizontal"
                       HorizontalAlignment="Center"
                       />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentControl Style="{DynamicResource InputControlStyle}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Our ItemsControl Declaration Thus Far

OK! Great, let’s see what our ItemsControl looks like now (for our example, we only have enough width available for there to be two columns):

Better Looking Input Field Rows

Better Looking Input Field Rows

Looking much better! But…hmm…they are still a bit scrunched together. Remember that the x-Dimension of a WrapPanel is constrained to its content, much like the StackPanel. There is no feature made available by the WrapPanel class which will space things out nicely for us, instead we’re going to have to space our items out ourselves by adding margins to them.

So, alright…things look a bit scrunched starting where the first control ends and the beginning of the next control, and so on. Let’s then add a margin to the right of each item by amending our ItemTemplate with a Margin attribute like so:

<ContentControl Style="{DynamicResource InputControlStyle}"
                Margin="0,0,0,25"
                />

Adding a Margin to Our ItemTemplate Declaration

Alright, not too hard. Let’s look at it now:

Two Columns of Input Fields Looking Mighty Fine

Two Columns of Input Fields Looking Mighty Fine

Alright. Sweetness! If we give our form some more width, it’ll fill up three columns as was shown in some of the earlier screenshots in this article, if we remove even more width, we’ll skinny on down to a single row even:

One Column of Some Mighty Fine Input Fields

One Column of Some Mighty Fine Input Fields

Looks like our work here is done.

Good journeys, all.

© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.