问题
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?
回答1:
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.
回答2:
You've two questions here:)
- Where to make a decsion in
XAML
(DataTriggers
) or in codeTemplateSelector
- What are you overriding the whole
Style
or just theDataTemplate
. In your first sample you overrideStyle
, 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(?).
回答3:
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.
回答4:
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.
来源:https://stackoverflow.com/questions/8926024/controltemplate-with-datatrigger-vs-datatemplate-with-datatemplateselector