缩进wpf树视图中的顶层分层项

本文关键字:分层 wpf 视图 缩进 | 更新日期: 2023-09-27 18:05:23

我试图在WPF TreeView的顶层分层项之间提供分离(边距)。问题是,我不知道如何编写Style,使其仅适用于最上面的项目,而不是每个项目。

我的TreeView的代码看起来像这样:

<TreeView ItemContainerStyle="{StaticResource treeViewItemStyle}"
          ItemsSource="{Binding Container.RootRules}"
          KeyUp="treeView_KeyUp"
          SelectedItemChanged="TreeView_SelectedItemChanged">
  <TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type me:HybridForecastRulesViewModel}"
                              ItemsSource="{Binding Children}">
      <Border Name="bd"
        ...
      </Border>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type me:RootRulesViewModel}"
                              ItemsSource="{Binding Rules}">
      <Grid>
        ...
      </Grid>
    </HierarchicalDataTemplate>
  </TreeView.Resources>
</TreeView>

我有一个像这样的treeviewitem的样式:

<Style x:Key="treeViewItemStyle"
       BasedOn="{StaticResource {x:Type TreeViewItem}}"
       TargetType="{x:Type TreeViewItem}">
  <Setter Property="Margin" Value="0,10,0,0" />
  <Style.Triggers>
    <DataTrigger Binding="{Binding IsVisible}" Value="False">
      <Setter Property="Visibility" Value="Collapsed" />
    </DataTrigger>
  </Style.Triggers>
</Style>

但是这个样式适用于两种类型的项目(RootRulesViewModelHybridForecastRulesViewModel),当我希望它只适用于RootRulesViewModel类型的项目时。如何做到这一点?

锦上添花的是,除了第一个项目,所有RootRulesViewModel项目的top Margin都为10。

缩进wpf树视图中的顶层分层项

TreeViewItem没有Level属性。

所以你有两个选项:

1)。看看TreeLevelConverter,它很有趣。它们绑定控件本身并使用转换器检索Level。在您的示例中,您可以扩展转换器,以便在它检索Level之后,将其转换为Thickness实例以用作Margin

2)你可以在你的ViewModels上创建一个Level属性(可能在它们的基类中,以避免代码重复)。然后,每次向ViewModel节点添加子节点时,都要在该子节点上设置Level。在xaml中,您将Margin属性绑定到ViewModel上的Level,使用一个转换器,根据Level是否为1返回不同的Thickness

编辑:

这是如何为所有的TreeViewItem设置一个通用的Style:

<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
      <Setter 1 .../>
      <Setter 2 .../>
      <Setter Property="Margin"
              Value="{Binding Level, Converter={StaticResource LevelToMarginConverter}}"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.Resources>
    <!-- here your hierarchical DataTemplate... -->
    <HierarchicalDataTemplate ... />
  </TreeView.Resources>
</TreeView>

我实际上已经有了一个解决方案。我不确定它有多好,所以我愿意听取建议来改进。

我从这个答案中编写了一个对象转换器,以获得TreeViewItemHeader中的对象类型。代码看起来像这样:

            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Header, Converter={StaticResource ObjectTypeConverter}}"
                             Value="RootRulesViewModel">
                    <Setter Property="Margin"
                            Value="0,0,0,10" />
                </DataTrigger>
                <DataTrigger Binding="{Binding IsVisible}"
                             Value="False">
                    <Setter Property="Visibility"
                            Value="Collapsed" />
                </DataTrigger>
            </Style.Triggers>
        </Style>

其中ObjectTypeConverter是我的自定义转换器,它将对象类型转换为字符串值。