【问题标题】:How to define a different style on a TreeViewItem based on Type如何根据 Type 在 TreeViewItem 上定义不同的样式
【发布时间】:2013-12-09 20:42:05
【问题描述】:

我有自己的基于this post 的树视图实现,但我在根据树视图项中的对象类型定义不同样式时遇到问题。我知道简单的方法是定义一个模板选择器,但是当你有两个 HierarchicalDataTemplates 时,我无法弄清楚这将如何工作。

 <HierarchicalDataTemplate DataType="{x:Type domainLayer:Folder}" ItemsSource="{Binding Converter={StaticResource BaseTypeConverter}}" />
 <HierarchicalDataTemplate DataType="{x:Type domainLayer:Document}" ItemsSource="{Binding Converter={StaticResource BaseTypeConverter}}" />

我使用这些模板来延迟加载我的树,效果很好。还为所有 TreeListViewItems 定义了一个样式。也许也有解决方案,但我不知道如何定义我的 TreeListViewItem 是文件夹还是文档。

非常感谢任何帮助。如果您需要更多代码,请告诉我!

上午 10:40 更新:

在样式中,为每个 TreeListViewItem 定义行:

<Style x:Key="cxc" TargetType="{x:Type local:TreeListViewItem}">
    <Setter Property="FontFamily" Value="TradeGothic LT" />
    <Setter Property="FontSize" Value="14px" />
    <Setter Property="Foreground" Value="{StaticResource TextBrush}" />
    <Setter Property="Background" Value="Transparent" />
    <EventSetter Event="MouseDoubleClick" Handler="OnItemMouseDoubleClick" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TreeListViewItem}">
                <StackPanel>
                    <Border Name="Bd"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}">
                        <GridViewRowPresenter x:Name="PART_Header"
                                                Content="{TemplateBinding Header}"
                                                Columns="{Binding Path=Columns,RelativeSource={RelativeSource AncestorType={x:Type local:TreeListView}}}"
                                                />
                    </Border>
                    <ItemsPresenter x:Name="ItemsHost" />
                </StackPanel>
                <ControlTemplate.Triggers>
<!-- ... -->

当我将模板(StackPanel 标记中的所有内容)复制到 HierarchicalDataTemplate 时,出现错误:在“ContentPresenter”类型上找不到静态成员“BackgroundProperty”。

【问题讨论】:

标签: wpf xaml hierarchicaldatatemplate


【解决方案1】:

您似乎对 WPF 提供的不同 Templates 有点困惑。首先,我们可以为TreeViewItemItemContainerStyle)定义一个Style,即数据项“容器”。然后我们可以为容器中出现的数据项(ItemTemplate)定义一个DataTemplate,或者在您的情况下为HierarchicalDataTemplate

因此,不要尝试将您的数据项 Binding 放入 ItemContainerStyle 中,也不要尝试将您的 UI 元素 Binding 放入 DataTemplate 中,您应该没问题。请注意,您可以提供一个DataTemplate/HierarchicalDataTemplate无需为集合中的每种数据类型设置其x:Key 属性,并且无需使用DataTemplateSelector...让 WPF根据数据项的类型隐式选择DataTemplates。这是一个简单的例子:

在代码中:

public class BaseClass { }

public class ClassA : BaseClass { }

public class ClassB : BaseClass { }

...

public Observablecollection<BaseClass> Items { get ; set; }

在 XAML 中:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.Resources>
        <DataTemplate DataType="{x:Type DataTypes:ClassA}">
            <Ellipse Fill="Red" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type DataTypes:ClassB}">
            <Rectangle Fill="Blue" />
        </DataTemplate>
    </ListBox.Resources>
</ListBox>

这个ListBox 将为ClassA 项目显示红色圆圈,为ClassB 项目显示蓝色矩形。你可以对你的文件夹和文件做类似的事情

【讨论】:

  • 嗨,Sheridan,感谢您的回复。感谢您清除此问题,因为我真的对此感到困惑。但是,我认为这不适用于我想要的,因为我需要很多重叠。但是,我已经修好了。我会回答自己。
  • 尽管这现在有效,但我必须回到我的陈述,因为这不是正确的方法:我现在遇到的问题是对于完全相同的 TreeView,但具有不同的对象,我必须为这些对象创建一个全新的样式。有什么想法吗?
  • 记住,不是Styles...数据对象 DataTemplates。您需要为您使用的每种数据类型创建一个新的DataTemplate,但我不认为这是一个问题......只是常态。
  • 也许我采取的方法太简单了,但我尝试将样式中的模板代码复制到 HierarchicalDataTemplate。我在样式上遇到了一些错误(例如 Background 属性),但也许这就是您所说的:只需复制没有 UI 样式的模板。我会先试试。再次感谢!
  • 老兄,您似乎还没有完全掌握它......真的不需要DataTemplateSelectors 或DataTriggers 做任何这些。您所需要的只是每个数据类型的DataTemplate/HierarchicalDataTemplate,仅此而已。不过,如果您对自己所拥有的感到满意,那也没关系。
【解决方案2】:

我已经解决了我的问题如下。在上述样式中,我添加了一个新的 MultiDataTrigger:

<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition
            Binding="{Binding RelativeSource={RelativeSource Self}, Path=Header, Converter={StaticResource IsFolder}}"
            Value="False" />
        <Condition
            Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}"
            Value="True" />
    </MultiDataTrigger.Conditions>
    <Setter TargetName="Bd"
            Property="Background"
            Value="{StaticResource HighlightBackgroundBrush}" />
</MultiDataTrigger>

这似乎可行,并且看起来是正确的解决方案。感谢 Sheridan 提供这方面的背景资料。

【讨论】:

    猜你喜欢
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    相关资源
    最近更新 更多