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

Есть ли способ использования наследования шаблонов данных в WPF?

Возможно ли иметь композицию или наследование DataTemplate (аналогично "BasedOn" в стилях)? Есть два случая, когда мне это нужно.

  • Для унаследованных классов: у меня есть базовый класс с несколькими унаследованными классами. Я не хочу дублировать шаблон базового класса в каждом из производного класса DataTemplate.

  • Различные представления: для того же класса я хочу определить datatemplate, а затем при необходимости добавить к этому шаблону. Ex. базовый шаблон будет отображать данные в объекте, а затем мне нужны разные шаблоны, которые могут выполнять разные действия над объектом, одновременно отображая данные (наследуя базовый шаблон).

4b9b3361

Ответ 1

Единственное, что я нашел для этого, это следующее:

<DataTemplate x:Key="BaseClass">
  <!-- base class template here -->
</DataTemplate>
<DataTemplate DataType="{x:Type app:BaseClass}">
  <ContentPresenter Content="{Binding}" 
                    ContentTemplate="{StaticResource BaseClass}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type app:DerivedClass}">
  <StackPanel>
    <ContentPresenter Content="{Binding}" 
                      ContentTemplate="{StaticResource BaseClass}"/>
    <!-- derived class extra template here -->
  </StackPanel>
</DataTemplate>

В основном это создает "общий" шаблон, на который можно ссылаться с помощью ключа (в данном случае BaseClass). Затем мы определяем реальный DataTemplate для базового класса и любых производных классов. Шаблон производного класса затем добавил бы его собственный "материал".

Было некоторое обсуждение об этом на msdn некоторое время назад, но никто не придумал лучшего решения, которое я видел.

Ответ 2

@Fragilerus и @Liz, на самом деле я думаю, что я придумал что-то лучшее. Вот еще один подход, который не только избегает дополнительной привязки ContentPresenter, но также устраняет необходимость применения шаблона в шаблоне, поскольку общий контент - это прямой контент, который установлен во время компиляции. Единственное, что происходит во время выполнения, - это привязки, которые вы устанавливаете внутри прямого содержимого. Таким образом, это значительно ускоряет пользовательский интерфейс по сравнению с другим решением.

<!-- Content for the template (note: not a template itself) -->
<Border x:Shared="False" 
        x:Key="Foo" 
        BorderBrush="Red" 
        BorderThickness="1" 
        CornerRadius="4">
    <TextBlock Text="{Binding SomeProp}" />
</Border>

<DataTemplate x:Key="TemplateA">
    <!-- Static resource - No binding needed -->
    <ContentPresenter Content="{StaticResource Foo}" /> 
</DataTemplate>

<DataTemplate x:Key="TemplateB">
    <!-- Static resource - No binding needed -->
    <ContentPresenter Content="{StaticResource Foo}" />
</DataTemplate>

Важно. Обязательно используйте атрибут x:Shared в своем общем содержимом, иначе это не сработает.

Путь WPF'y

Из сказанного выше, это действительно не самый удобный для WPF способ делать то, что вам нужно. Это может быть достигнуто с помощью класса DataTemplateSelector, который выполняет именно это... выбор шаблона данных на основе любых критериев, которые вы установили.

Например, вы можете легко установить один из них, который ищет ваши известные типы данных, и возвращает один и тот же DataTemplate для обоих из них, но для всех остальных типов он возвращается в систему для разрешения DataTemplate. Это то, что мы на самом деле делаем здесь.

Надеюсь, это поможет!:)