WPF 数据模板绑定取决于属性类型

21

我有一个对象集合,绑定到分层数据模板,每个对象都有一个属性(我们称之为属性“A”),它是某种类型。这种类型在每个对象之间都不同。

如果数据模板包含图像和一些文本,那么根据属性“A”的类型更改在模板中显示的图像应该采用什么最好的方法?

我知道我可以将其放入转换器并手动在代码中执行绑定转换,但由于WPF提供了所有的绑定设施,我认为可能有更好的方法。

3个回答

42

如果您创建本地数据模板并使用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(); } }

(当A的值发生变化时,您还需要为AType引发PropertyChanged。)完成此操作后,您应该能够在样式中实现数据触发器,例如:

<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>

1

我认为您可以使用触发器来完成这个任务。

<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>

如果我使用数据模板选择器,那么难道不需要为每种类型的项创建一个新模板吗? - gmn
是的。也许我误解了你的意思。我编辑了我的答案。 - Matěj Zábský

1

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>

虽然我还没有测试过,但是想法就是这样。


这似乎并没有回答问题:“根据属性的类型”。 - Josh Noe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接