WPF DataTemplate Связывание в зависимости от типа свойства

У меня есть набор объектов, привязанных к шаблону иерархических данных, каждый из моих объектов имеет свойство на них (позволяет называть его свойством "А" ) определенного типа. Этот тип зависит от каждого из объектов.

Если в шаблоне данных есть изображение и какой-то текст, каким образом было бы лучшим способом изменить изображение, отображаемое в шаблоне, в зависимости от типа свойства "A".

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

Ответ 1

Это довольно просто сделать в шаблоне данных, если вы создаете локальные шаблоны данных и используете ContentPresenter. Этот шаблон представляет объекты типа MyObject, отображающие изображение, источник которого определяется типом свойства A рядом с TextBlock, который отображает содержимое свойства Text:

<DataTemplate DataType="{x:Type MyObject}">
   <StackPanel Orientation="Horizontal">
      <StackPanel.Resources>
         <DataTemplate DataType="{x:Type Thing1}">
            <Image Source="thing1.png"/>
         </DataTemplate>
         <DataTemplate DataType="{x:Type Thing2}">
            <Image Source="thing2.png"/>
         </DataTemplate>
      </StackPanel.Resources>
      <ContentPresenter Content="{Binding A}"/>
      <TextBlock Text="{Binding Text}"/>
   </StackPanel>
</DataTemplate>

Если вы хотите использовать стили для этого, вместо этого вы столкнетесь с проблемой, потому что триггеры данных хотят посмотреть значения свойств, а тип свойства A сам по себе не отображается как свойство.

Если, конечно, вы не реализуете одно:

public Type AType { get { return A.GetType(); } }

(Вы также должны поднять PropertyChanged для AType, когда изменяется значение A.) После того, как вы это сделали, вы сможете реализовать триггер данных в стиле, например:

<Style TargetType="Image">
   <Setter Property="Source" Value="default.png"/>
   <Style.Triggers>
      <DataTrigger Binding="{Binding AType}" Value="{x:Type Thing1}">
         <Setter Property="Source" Value="thing1.png"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding AType}" Value="{x:Type Thing2}">
         <Setter Property="Source" Value="thing2.png"/>
      </DataTrigger>
   </Style.Triggers>
</Style>

Ответ 2

Я думаю, вы можете сделать это с помощью triggers.

<Image.Style>
    <Style TargetType="{x:Type Image}">
        <Setter Property="Source" Value="Path">
        <Style.Triggers>
            <DataTrigger Binding="{Binding TheProperty}" Value="TheValue">
                <Setter Property="Source" Value="NewPath"/>
            </DataTrigger>
        </Style.Triggers>
     </Style>
</Image.Style>

Ответ 3

DataTemplateSelector, похоже, не является хорошим выбором, поскольку у вас есть один и тот же шаблон для всех значений A.

Используйте DataTriggers:

<DataTemplate>
    <StackPanel>
        <Image x:Name="image" />
        <TextBlock>Your text</TextBlock>
    </StackPanel>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=A}" Value="ValueToCheck1">
            <DataTrigger.Setters>
                <Setter Property="Source" Value="Image1.png" TargetName="image" />
            </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=A}" Value="ValueToCheck2">
            <DataTrigger.Setters>
                <Setter Property="Source" Value="Image2.png" TargetName="image" />
            </DataTrigger.Setters>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

Не тестировали, но идея такая.