Подтвердить что ты не робот

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, лучше, но хотел бы знать от вас -

  • Какой из них лучше и почему?

  • Будет ли разница в производительности в два?

4b9b3361

Ответ 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 и т.д. Но вам это нужно? Если вы этого не сделаете, элемент управления может быть переполнен.