ControlTemplate с DataTrigger Vs. DataTemplate с DataTemplateSelector
У меня есть общий элемент управления, который отображает редактор, основанный на свойстве type внутри ViewModel. В настоящее время он реализован с использованием Control
, ControlTemplate
и DataTrigger
как это -
<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>
Теперь это может быть достигнуто с помощью ContentPresenter
, DataTemplate
и DataTemplateSelector
, как это, -
<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
Я чувствую, что второй подход, используя DataTemplateSelector
, лучше, но хотел бы знать от вас -
Ответы
Ответ 1
Я слышал, что DataTemplateSelectors
не обновляет шаблон, если значение, на котором они основаны на изменениях, и из-за этого я обычно их не использую.
Мой предпочтительный метод - фактически использовать DataTemplates.
<MyControl.Resources>
<DataTemplate TargetType="{x:Type local:BooleanModel}">
<local:BooleanView />
</DataTemplate>
<DataTemplate TargetType="{x:Type local:IntegerModel}">
<local:IntegerView />
</DataTemplate>
...
</MyControl.Resources>
Во-вторых, если я хочу изменить шаблон на основе свойства, а не типа объекта, я предпочитаю использовать DataTriggers
. Это связано с тем, что если это свойство когда-либо изменено, уведомление PropertyChange будет автоматически сообщать пользовательскому интерфейсу, что он изменился, и обновить шаблон. Я не считаю, что DataTemplateSelectors
сделать это автоматически. Я также предпочитаю видеть логику выбора шаблона в своем XAML, не скрывать его в файле TemplateSelector, но это только личные предпочтения.
И мой последний выбор - использовать DataTemplateSelector
. Я почти никогда не использую его в приложении WPF, хотя часто это делаю в Silverlight, так как он не поддерживает мой предпочтительный метод использования неявного DataTemplates
(пока)
Я не знаю каких-либо существенных различий в производительности между ними, хотя мне было бы интересно, если кто-то скажет мне об этом.
Ответ 2
У вас есть два вопроса:)
- Где сделать деление в
XAML
(DataTriggers
) или в коде TemplateSelector
- Что вы делаете над всем целым
Style
или просто DataTemplate
. В первом примере вы переопределяете Style
, во втором - DataTemplate
.
Вот мой 2c:
Я бы придерживался триггеров, так как вы получите непревзойденный уровень гибкости с ними - новый редактор по цене нового ресурса и триггер всего в XAML - что может быть лучше? Существует один потенциальный оговорка, связанная с использованием DataTrigger - это может привести к утечкам данных.
Говоря о выборе Style
vs DataTemplate
, я снова использую Style
. Это может быть немного более тяжелым визуальным деревом, но это даст вам окончательный контроль над вашими редакторами.
В частности, некоторые свойства могут быть определены только на уровне Style
, используя Style
Setters
.
Определение уровня @ DataTemplate
просто не будет работать, так как ваш контент DataTemplate
не является непосредственным дочерним элементом вашего контейнера управления (там есть дополнительный уровень - элемент управления actula). Если у вас нет таких свойств, ControlTemplates
тоже хороши и, вероятно, быстрее (?).
Ответ 3
Я также не фанат DataTemplateSelector, но, думаю, вы могли бы использовать их, если ваша оценка селектора состоит не только из проверки типов, например, if x>5 && dayOfWeek==Tue && isFullMoon(today)
то template1.
Ответ 4
Я бы предположил, что ответ более важен, как вам кажется, control
. Вы получаете целую кучу функциональности с control
, который на самом деле не доступен с помощью DataTemplate
. Вы можете добавить DependencyProperties
, events
, functions
и т.д. Но вам это нужно? Если вы этого не сделаете, элемент управления может быть переполнен.