ControlTemplate with DataTrigger Vs. DataTemplate with DataTemplateSelector
Asked Answered
B

4

12

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?
Bozen answered 19/1, 2012 at 12:29 Comment(1)
From what i gather, the second way is considered best practice. It also much more readable since it doesn't hold the logic of selection (which should always be defined in C#). However I'm interested as well on the performance point.Landlord
H
9

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.

Hernardo answered 19/1, 2012 at 13:54 Comment(5)
Interesting, I'm almost sure the question was about WPF, just out of curiosity - did they fix up implicit templates in SL4/5 as I know they weren't available in the prev versions.Chorea
@Dmitry I believe the last Silverlight project I did was in 4.0, and implicit DataTemplates didn't work then. I heard they work in 5.0, but haven't it yet.Hernardo
+1 for 'DataTemplateSelectors do not update the template if the value they're based on chan'. I checked this and the template doesn't update if value changes. thanks.Bozen
That's not always true. If you have a ContentPresenter with Content={Binding Path=SomeProp} then if SomeProp changes the ContentPresenter will ask the TemplateSelector for the template again. However if SomeProp does NOT change but a property of that object changes then you won't get a call to the template selector again.Airla
Here is datatemplateselector exmaple from @Hernardo change-data-template-dynamicallyWorship
C
3

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(?).

Chorea answered 19/1, 2012 at 13:56 Comment(2)
Thanks Dmitry, can you provide more details about 'DataTrigger causing data leaks'?Bozen
@Bozen - Sorry I won't be able to come up with a exact repro, this is rather an observation, I've seen a few projects which benefit grately after reducing the number of triggers.Chorea
L
1

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.

Luciana answered 9/1, 2019 at 12:1 Comment(1)
Yes, if complex logic is required then DataTemplateSelector is useful; although some cases can still be achieved through MultiDataTrigger too.Bozen
A
0

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.

Airla answered 6/7, 2012 at 3:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.