在一个 TreeViewItem 中连接字符串列表

Concat list of strings in one TreeViewItem

目前我正在深入研究 WPF,但遇到以下问题:

我的数据模型(见下文)具有 3 层的分层数据(一个文件、文件中的一行、分段的行)。我想在 TreeView 中显示 2 个级别,这样第一级是文件,第二级项目是 TextParts 列表的连接字符串(根据 IsMatch [= 格式不同) 53=]).

所以这个样本数据

{ fileA("filename1"): { 
    line1: { part1("text1", false), part2("text2", true), part3("text3", false) }, 
    line2: { part4("text4", false) } 
} }

应该看起来像:

(备注:我这里用的是粗体和斜体,而不是xaml中用的白底和黄底)

我已经阅读了 this MS 文档,这让我对整个问题有了很大的了解。我不确定这是否可以在 xaml 中完成,或者是否可以以某种方式在代码隐藏中生成模板?

我的数据模型:

class MyModel {
    public ObservableCollection<ResultFile> FileLines { get; }
}
class ResultFile {
    public ObservableCollection<ResultLine> Lines { get; }
    public string Name { get; set; }
}
class ResultLine {
    public ObservableCollection<ResultTextPart> TextParts { get; }
}
class ResultTextPart {
    public string Text { get; set; }
    public bool IsMatch { get; set; }
}

Xaml:

<TreeView x:Name="TvSearchResults">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type m:ResultFile}" ItemsSource="{Binding Lines}">
            <StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}"/> <!-- ... --> </StackPanel>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type m:ResultLine}">
            <!-- how to display the list of ResultTextPart as single line ? -->
        </DataTemplate>
        <DataTemplate DataType="{x:Type m:ResultTextPart}">
            <TextBlock Text="{Binding Text}" Name="tviTextPart" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsMatch}" Value="true">
                    <Setter Property="Background" TargetName="tviTextPart" Value="Yellow"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

这基本上可以满足您的要求。虽然文本之间没有任何空格,但您可以使用转换器或其他东西添加它。甚至可能删除整个 ItemsControl 并让转换器接受集合并脱口而出一个字符串,我只是想为您将其全部保留在 xaml 中。

<TreeView x:Name="TvSearchResults" Width="200" Margin="20" ItemsSource="{Binding Data.FileLines}">
<TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Lines}">
        <TextBlock Text="{Binding Path=Name}"/>
        <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding TextParts}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Text}">
                                <TextBlock.Style>
                                    <Style TargetType="TextBlock">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Path=IsMatch}" Value="True">
                                                <Setter Property="FontWeight" Value="Bold"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </TextBlock.Style>
                            </TextBlock>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </DataTemplate>
        </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>    
</TreeView.ItemTemplate>
</TreeView>

为简单起见:

<DataTemplate DataType="{x:Type m:ResultLine}">
    <ItemsControl ItemsSource="{Binding TextParts}" >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</DataTemplate>

所以您实际上只需要使用 ItemsControl 并为此容器设置水平方向的面板。