24
votes

Recently I'm trying to reuse some UI elements in my application. When I started programming with WPF I'm told that DataTemplate is the best way to reuse UI elements. You can define a template for your data entity and use it everywhere. It sounds very good. However, I also found some disadvantages, especially when it is compared with UserControl.

  1. You cannot reuse a DataTemplate defined in another Window or UserControl. For example, if UserDataTemplate is define in WindowA.xaml, you cannot use it in WindowB.xaml. The solution might be that put the DataTemplate as a resource in a global Resource Dictionary.
  2. DataTemplate is hard to have some code behind. As mentioned in item 1, if you put the DataTemplate in a ResourceDictionary, there is no place to put your code by default. I googled the problem and yes, I found a trick to make the ResourceDictionary have a cs file. But it still has another problem.
  3. Another problem of DataTemplate is that you must be clear with the difference between the instance of DataTemplate itself and the instances of the content of DataTemplate. A DataTemplate will have only one "instance of DataTemplate", and may have many instances of the content of the DataTemplate. Let me explain it with an Example:

    <DataTemplate>
            <DataTemplate.Resources>
                    <my:User x:key="User1"/>
            </DataTemplate.Resources>                
            <Grid MouseLeftButtonDown="OnMouseLeftButtonDown">
                    <Grid.Resources>
                            <my:User x:key="User2"/>
                    </Grid.Resources>
            </Grid>        
    </DataTemplate>
    
    
    public partial class CodeBehind
    {
             Point mousePos = new Point();
    
            private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)  
            {
                    mousePos = e.Pos...;
            }
    }
    

The result will be that : User1 will only have one instance, however, a User2 instance will be created once the DataTemplate is applied, which means User2 will have many instances if the datatemplate is being applied many times. However, unlike UserControl, the field "mousePos" will NOT have many copies. If the DataTemplate is being applied 100 times, the mousePos won't have 100 copies, which mean the 100 Grids will use the only one mousePos field as the same time, which may cause problems. In UserControl, the field you defined will only be used by the control. 100 UserControl instances will have 100 field copies.

Maybe I'm using DataTemplate in the wrong way. Any comment is appreciated.

Best regards,

Zach

3

3 Answers

32
votes

Conceptually DataTemplates and UserControls solve two different problems. They are not really interchangeable so your comparisons are not really accurate.

DataTemplates are all about applying a visual style to a DataType. Typically what this means is I have my own .NET class called Foo and I want to give it a visual style. I would do this by creating a DataTemplate with a DataType of Foo.

I can then place this DataTemplate in my application (say in App.XAML) and I will have my visual style applied to my data object Foo wherever it is used. Often this means you will see a ContentControl that has a Content property bound to a property of type Foo.

UserControls on the other had are all about organization of XAML. A user control helps in organizing chunks of XAML that you want to re-use throughout your application that has behaviors and functionality tied to it. This is more than what a DataTempate will do.

A DataTemplate is tied to one DataType and display a visual for that type. A UserControl can be composed of multiple DataTypes and can include custom behaviors.

That being said, I very rarely find the need for a UserControl. I use DataTemplates all over to model my data and implement my behaviors though data bindings and the MVVM pattern.

12
votes

Personally, I create a UserControl and then make a DataTemplate from that. This has to following advantages, to me:

  1. Can use across windows, only by re-defining the DataTemplate part.
  2. Can use code-behind (I know, I know, but some things are just so much easier using code-behind, I don't see the point in unnecessary complicating my code based on dogma).
  3. XAML designer support.
2
votes

About 2.

I'd say that DataTemplates are not designed to be used with code-behind. You can most of the case only use DataBinding and Commands to wire the logic between your model and its representation. Not having code-behind also facilitate the unit tests of you application.