6

我在弄清楚如何模板化以下 TreeView 项目布局时遇到了一些困难:

TreeView 项目布局模型

我有几个项目,SearchList,其中包含一个 Search 集合,其中包含一个 DataSet 集合(有点,但这是题外话)。我遇到的困难是按照我想要的方式设计每个节点级别。我正在使用 MVVM,并且 TreeViews ItemsSource 属性设置为 SearchListViewModels 的 ObservableCollection,它又包含我的对象,一直沿对象树向下。

我可以成功设置 SearchList HierarchicalDataTemplate 的样式以正确显示它们。我挂断的地方是 SearchTerm 节点样式。我希望在 SearchTerm 内容区域右侧的包装面板或统一网格(我还没有决定)中表示数据集。我已经修改了一个 TreeViewItem 控件模板,使其具有我认为的这种行为方式),但是如果我在 Search HierarchicalDataTemplate 的 ItemContainerStyle 属性中设置它,它什么也不做。显示的只是搜索的内容。

我改变的 TreeViewItem 模板

<Style TargetType="{x:Type TreeViewItem}" x:Key="AlteredTreeViewItem">
    <Setter Property="HorizontalContentAlignment"
        Value="Stretch" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"
                            MinWidth="19" />
                        <ColumnDefinition Width="0.414*" />
                        <ColumnDefinition Width="0.586*"/>
                    </Grid.ColumnDefinitions>
                    <Border x:Name="Bd" HorizontalAlignment="Stretch"
                        Grid.Column="1" Grid.ColumnSpan="1" Background="#7F058956">
                        <ContentPresenter x:Name="PART_Header" Margin="10,0" />
                    </Border>
                    <WrapPanel x:Name="ItemsHost"
                        Grid.Column="2" IsItemsHost="True"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的搜索分层数据模板

    <HierarchicalDataTemplate DataType="{x:Type local:SearchViewModel}"  ItemsSource="{Binding MySearch.Custodians}" ItemContainerStyle="{StaticResource AlteredTreeViewItem}">
        <TextBlock Text="{Binding MySearch.SearchName}" Foreground="Black" FontFamily="Arial" FontSize="16"/>
    </HierarchicalDataTemplate>

当然,既可以采用不同的样式,又可以有不同的子项目布局?如何做到这一点?

4

2 回答 2

6

看来你已经很接近你所追求的了。我尝试根据您发布的代码重新创建您的场景,并注意到它存在一些问题(当然这是基于我对您发布的代码的解释)

  • 你错过ContentSource="Header"ContentPresenter
  • 我认为您ItemContainerStyle在错误的HierarchicalDataTemplate级别上应用了。应该在父母身上指定它以影响孩子(在你的情况下SearchListViewModel)。
  • 默认Template的 for以一定的尺寸TreeViewItem布局,因此除非您也修改父级的 ,否则不会成功换行。我在下面的示例中将其更改为 aContentPresenterAutoColumnDefinitionWrapPanelItemContainerStyleUniformGrid

通过上面的更改和其他一些事情,我得到了一个看起来像这样的结果,希望非常接近你所追求的

在此处输入图像描述

我在这里上传了示例解决方案:https ://www.dropbox.com/s/4v2t8imikkagueb/TreeViewAltered.zip?dl=0

这是它的 Xaml 代码(代码太多,无法全部发布......)

<Window.Resources>
    <!-- DataSet-->
    <HierarchicalDataTemplate DataType="{x:Type data:DataSet}">
        <Border BorderThickness="3"
                BorderBrush="Gray"
                Background="Green">
            <TextBlock Text="{Binding Path=Tables[0].TableName}"
                       Margin="5"/>
        </Border>
    </HierarchicalDataTemplate>

    <!-- SearchViewModel -->
    <HierarchicalDataTemplate DataType="{x:Type viewModel:SearchViewModel}"
                              ItemsSource="{Binding DataSets}">
        <TextBlock Text="{Binding DisplayName}"
                   Foreground="Black"
                   FontFamily="Arial"
                   FontSize="16"/>
    </HierarchicalDataTemplate>

    <!-- SearchListViewModel -->
    <HierarchicalDataTemplate DataType="{x:Type viewModel:SearchListViewModel}"
                              ItemsSource="{Binding SearchList}">
        <HierarchicalDataTemplate.ItemContainerStyle>
            <Style TargetType="TreeViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TreeViewItem}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" MinWidth="19" />
                                    <ColumnDefinition Width="0.414*" />
                                    <ColumnDefinition Width="0.586*"/>
                                </Grid.ColumnDefinitions>
                                <Border x:Name="Bd"
                                        HorizontalAlignment="Stretch" 
                                        Grid.Column="1"
                                        Grid.ColumnSpan="1"
                                        Background="#7F058956">
                                    <ContentPresenter x:Name="PART_Header"
                                                      ContentSource="Header"
                                                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                                </Border>
                                <UniformGrid x:Name="ItemsHost"
                                             Grid.Column="2"
                                             Columns="3"
                                             IsItemsHost="True"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </HierarchicalDataTemplate.ItemContainerStyle>
        <TextBlock Text="{Binding DisplayName}"
                   FontSize="20"/>
    </HierarchicalDataTemplate>
</Window.Resources>
<Grid>
    <TreeView ItemsSource="{Binding SearchListViewModels}" />
</Grid>
于 2011-11-07T22:36:54.627 回答
3

很久以前,我在尝试创建类似界面时学到的一点是,使用 a比使用 a更好ListBoxTreeView

为什么?

  1. 如果您只有一个扩展级别(从您的示例中显示),您将对布局进行更多控制,因为您只有一个DataTemplate样式。

  2. ListBox定制 a比定制 a 容易得多,TreeView因为您不必关心GridViewColumnHeaderandGridViewColumnPresenters等。

要获得扩展部分(这就是您最初选择 a 的原因TreeView),只需使用Grid定义了两行的a Expander,并将第二行中的 a 绑定到IsCheckeda 的属性ToggleButton。请参阅我从Log Viewer中提取的示例。

<DataTemplate>
    <Grid Margin="0,0,0,3" Grid.IsSharedSizeScope="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30" SharedSizeGroup="SSG_TimeIcon"/>
            <ColumnDefinition Width="120" SharedSizeGroup="SSG_Time"/>
            <ColumnDefinition Width="30" SharedSizeGroup="SSG_LevelIcon"/>
            <ColumnDefinition Width="70" SharedSizeGroup="SSG_Level"/>
            <ColumnDefinition Width="*" SharedSizeGroup="SSG_Message"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <!-- ProgramTime -->
        <Rectangle Grid.Column="0" Grid.Row="0" Margin="0,0,0,0" Width="16" Height="16" VerticalAlignme="Top"  HorizoalAlignme="Stretch" Fill="{StaticResource Icon_Timer}"/>
        <TextBlock Grid.Column="1" Grid.Row="0" Margin="5,0,0,0" VerticalAlignme="Top" HorizoalAlignme="Stretch" Text="{Binding Path=TimeStamp, Converter={StaticResource ObjectToStringConverter}}" ToolTip="{Binding Path=ProgramTime}"/>
        <!-- Level -->
        <Rectangle Grid.Column="2" Grid.Row="0" Margin="10,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{Binding Path=Level, Converter={StaticResource MappingConverterNinjaLogLevelEnumToBrushResource}}"/>
        <TextBlock Grid.Column="3" Grid.Row="0" Margin="5,0,0,0" Text="{Binding Path=LevelFriendlyName}" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
        <!-- Message -->
        <StackPanel Grid.Column="4" Grid.Row="0" Margin="10,0,0,0" Orieation="Horizoal" >
            <TextBlock Margin="0,0,0,0" Text="{Binding Path=LogMessage}" TextWrapping="Wrap" VerticalAlignme="Top"  HorizoalAlignme="Stretch"/>
            <ToggleButton x:Name="ExpandExceptiooggleButton" VerticalAlignme="Top" Margin="5,0,0,0" IsChecked="False" 
                          Coe="Show Details" Tag="Hide Details" Style="{StaticResource TextButtonStyle}"
                          Foreground="{StaticResource BlueBrush}" Background="{StaticResource RedBrush}"
                          Visibility="{Binding Path=HasException, Converter={StaticResource BoolToVisibilityConverter}}" />
        </StackPanel>
        <Expander IsExpanded="{Binding Path=IsChecked, ElemeName=ExpandExceptiooggleButton}" Style="{StaticResource CoeExpanderStyle}" 
                  Margin="10,0,0,0" Grid.Column="4" Grid.Row="1">
            <Border BorderBrush="{StaticResource DarkGreyBrush}" BorderThickness="1,0,0,0">                                
                <TextBlock Text="{Binding Path=Exception}" Margin="5,0,0,0"/>
            </Border>
        </Expander>
    </Grid>
</DataTemplate>

你能看到定义标题和可扩展正文是多么容易吗?如果您确实需要嵌套数据,请在视图模型中添加一个 Level 属性(您使用的是 MVVM 不是吗?!),然后创建一个IValueConverter返回 Margin (即Thickness)来伪造缩进。

于 2011-11-08T16:54:54.390 回答