Question

I have a generic control which displays an editor based on the type property inside a ViewModel. Currently it's implemented using Control, ControlTemplate and DataTrigger like this -

<Control
   x:Name="MainControl"
   Grid.Column="1"
   TargetUpdated="OnTargetUpdated">
        <Control.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger
                        Binding="{Binding Path=EditorType}"
                        Value="{x:Static view:EditorType.Bool}">
                        <Setter
                            Property="Control.Template"
                            Value="{StaticResource boolTemplate}" />
                    </DataTrigger>
                    <DataTrigger
                        Binding="{Binding Path=EditorType}"
                        Value="{x:Static view:EditorType.Text}">
                        <Setter
                            Property="Control.Template"
                            Value="{StaticResource textTemplate}" />
                    </DataTrigger>
                    <DataTrigger
                        Binding="{Binding Path=EditorType}"
                        Value="{x:Static view:EditorType.Integer}">
                        <Setter
                            Property="Control.Template"
                            Value="{StaticResource integerTemplate}" />
                    </DataTrigger>
                    ...
                    ....
                </Style.Triggers>
            </Style>
     </Control.Style>
</Control>

Now, same can be achieved using ContentPresenter, DataTemplate and DataTemplateSelector like this -

<local:EditorTemplateSelector
    BoolEditorTemplate="{StaticResource boolTemplate}"
    TextEditorTemplate="{StaticResource textTemplate}"
    IntegerEditorTemplate="{StaticResource integerTemplate}"
    ...
    ....
    x:Key="EditorTemplateSelector">
</local:EditorTemplateSelector>

<ContentPresenter
    ContentTemplateSelector="{Binding Source={StaticResource EditorTemplateSelector}}"
    Content="{Binding}"
    TargetUpdated="OnTargetUpdated">
</ContentPresenter>

// Template selector returning appropriate template based on type

I feel the second approach, using DataTemplateSelector is better but would like to know from you -

  • Which one is better and why?

  • Will there be any performance difference in two?

Was it helpful?

Solution

I've heard that DataTemplateSelectors do not update the template if the value they're based on changes, and because of this I usually don't use them.

My preferred method is actually to use DataTemplates.

<MyControl.Resources>
    <DataTemplate TargetType="{x:Type local:BooleanModel}">
        <local:BooleanView />
    </DataTemplate>
    <DataTemplate TargetType="{x:Type local:IntegerModel}">
        <local:IntegerView />
    </DataTemplate>
    ...
</MyControl.Resources>

Second, if I want to change the template based on a property rather than the object type, I tend to use DataTriggers. This is because if that property ever gets changed, the PropertyChange notification will automatically tell the UI that it has changed and to update the template. I do not believe DataTemplateSelectors do this automatically. I also prefer to see the template selection logic in my XAML, not have it hidden in a TemplateSelector file, but that's just personal preference.

And my last choice is to use a DataTemplateSelector. I almost never use one in a WPF application, although I often do in Silverlight since it doesn't support my preferred method of using implicit DataTemplates (yet)

I am not aware of any significant performance differences between the two, although I would be interested if someone can tell me otherwise.

OTHER TIPS

You've two questions here:)

  1. Where to make a decsion in XAML(DataTriggers) or in code TemplateSelector
  2. What are you overriding the whole Style or just the DataTemplate. In your first sample you override Style, in the second one - DataTemplate.

Here're my 2c:

I'd stick with the Triggers, as you'll get an unbeatable flexibility level with them - a new editor for the price of new resource and a trigger all in XAML - what can be better? There's one potential caveat, related to DataTrigger usage - it may cause data leaks.

Talking of Style vs DataTemplate choice I's stick again with the Style. It might be a bit heavier visual tree wise, but it'll give you the ultimate control over the apperance of you editors.

In particular, some properties can only be defined at a Style level, using Style Setters's. Defining then @DataTemplate level simply won't work as your DataTemplate content is not an immediate child of your control container (there's an extra level - the actula Control). If you've no such properties, ControlTemplates are good too, and probably faster(?).

I'm also not a fan of DataTemplateSelector, but I guess you could use them if your selector-evaluation consists of more than type checking, e.g. if x>5 && dayOfWeek==Tue && isFullMoon(today) then template1.

I would suggest the answer is more one of do you think a control is necessary. You get a whole bunch of functionality with a control that is not really available with a DataTemplate. You can add DependencyProperties, events, functions etc etc. But do you need this? If you don't then a control might be overkill.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top