DataTemplates are a great feature introduced in WPF, it allows to determine how data is presented and how data binding accesses the presented data. Just as we can apply a visual style to a specific UI control, we can do it for a specific data type. There is just one problem here, DataTemplates are good for object types but not for interfaces…
Lets take a look at the following code, where ILibrary interface is defined and Library class implicitly implement ILibrary interface:
interface ILibrary { string PropertyA { get; } } class Library : ILibrary { public string PropertyA { get { return “Dev102″; } } }
Here is the XAML code where a data template for the Library object type is defined:
<Window.Resources>
<DataTemplate DataType=“{x:Type local:Library}”>
<TextBlock Text=“{Binding PropertyA}” />
</DataTemplate>
</Window.Resources>
<Grid>
<Canvas>
<Button Name=“buttonA“>
</Button>
</Canvas>
</Grid>
And here we set the button content:
public Window1() { InitializeComponent(); ILibrary lib = new Library(); this.buttonA.Content = lib; }
This is how the button looks when running this code, the button contains a text block that is binded to PropertyA which returns an hard coded string: “Dev102″.:
What happens if we change the data type of the data template to a non object type (the ILibrary interface), like this:
<DataTemplate DataType=“{x:Type local:ILibrary}”>
The result is that the data template is ignored:
Don’t try to find a bug in my code, after doing some search I understood that the reason for what happened here is simple: there is no support for interfaces. The WPF data team discussed this issue but could not come up with a good design for it. They had two major problems:
- There is multiple inheritance for interfaces. Think about a situation where the data source implement more than one interface and there are data templates for all of those interfaces. What data template shall be picked up?
- Reflection shall be used in order to support interfaces and that is not cheap.
As I demonstrated in the code above, although its not elegant, there is away out from this problem - create the data template for the object type (not for the interface). But, in the code above, I implicitly implemented the interface, what would happen if explicit implementation was used (Read about the 4 Key Differences Between Implicit and Explicit Interface Implementation)?
Take a look at the new explicit implementation:
class Library : ILibrary { string ILibrary.PropertyA { get { return “Dev102″; } } }
Now, there is no way to do a data template for the Library class too, this is what we get:
So, to put thing together, data templates for interfaces is not supported. If the object type implicitly implements that interface then there is a way out. If the object type explicitly implements the interface, there is no way to do a data template for it in WPF.
2 Trackback(s)