WPF中具有多个叶数据类型的TreeView

本文关键字:数据类型 TreeView WPF | 更新日期: 2023-09-27 18:29:36

我正在尝试创建一个具有以下层次结构的TreeView:

Device1
--File1
--File2
--Hook1
--Hook2
Device2
--File1
--File1
Device3
--Hook1

所以基本上根级节点是一个设备,其子节点是File和Hook。我用分层数据模板创建了以下树

<TreeView ItemsSource="{Binding Devices}">
        <HierarchicalDataTemplate DataType="{x:Type datamodel:Device}" ItemsSource="{Binding Files}">
               <TextBlock Margin="5,5,0,0" Text="{Binding DeviceName}"/>
                  <HierarchicalDataTemplate.ItemTemplate>
                       <DataTemplate  DataType="{x:Type datamodel:File}">
                            <TextBlock Margin="5,0,0,0" Text="{Binding FileName}"/>
                        </DataTemplate>
                 </HierarchicalDataTemplate.ItemTemplate>
       </HierarchicalDataTemplate>

     Class Devices
     {
          public string DeviceName
          {
             get;set;
          }
          public string List<File> Files
          {
              get;set;
          }
         public string List<Hook> Hooks
          {
              get;set;
          }
     }
  public class File
{
     public string FileName
     {
        get;set;
     }

     public string FileType
    {
        get;set;
    }
    public string Location
    {
        get; set;
    }
}

public class Hook
{
    public string HookName
    {
       get;set;
    }
    public string Type
   {
      get;set;
   }
}

我只能在层次结构数据模板的ItemTemplate中添加一个数据模板。如何在一个层次结构数据模板下指定两种数据类型??

WPF中具有多个叶数据类型的TreeView

您必须在此处使用转换器,它将返回包含文件和挂钩的CompositeCollection。您将使用此转换器与HierarchicalDataTemplate DataType="{x:Type datamodel:Device}"ItemsSource

然后,您只需要为File和Hook数据类型定义两个数据模板。

感谢

我尝试了CompositeCollection,但意识到绑定对象已转换为基类型。所以我将它与DataTemplateSelector结合使用。以下解决方案对我有效。

<TreeView ItemsSource="{Binding Devices}">
     <TreeView.Resources>
       <HierarchicalDataTemplate DataType="{x:Type datamodel:Devices}" ItemTemplateSelector="{StaticResource LeafDataTemplateSelector}">
            <HierarchicalDataTemplate.ItemsSource>
                 <MultiBinding Converter="{StaticResource CompositeCollectionConverter}">
                      <Binding Path="Files" />
                      <Binding Path="Hooks"/>
                 </MultiBinding>
            </HierarchicalDataTemplate.ItemsSource>
                <StackPanel Height="25" Orientation="Horizontal">
                   <Image Height="20" Width="20" Source="Device.png"/>
                    <TextBlock Margin="5,5,0,0" Text="{Binding Device}"/>
                </StackPanel>
           </HierarchicalDataTemplate>
         <DataTemplate x:Key="FileKey" DataType="{x:Type datamodel:File}">
                <StackPanel Height="25" Orientation="Horizontal" ToolTip="Installation File">
                     <Image Height="20" Width="20" Source="File.png" />
                      <TextBlock Text="{Binding FileName}"/>
                </StackPanel>
         </DataTemplate>
         <DataTemplate x:Key="HookKey"  DataType="{x:Type datamodel:Hook}">
               <StackPanel Height="25" Orientation="Horizontal"  ToolTip="Installation Hook">
                   <Image Height="20" Width="20" Source="Hook.png" />
                   <TextBlock Margin="5,5,0,0" Text="{Binding HookName}"/>
               </StackPanel>
         </DataTemplate>
    </TreeView.Resources>

已使用模板选择器根据键选择适当的模板。

 public class LeafDataTemplateSelector :  DataTemplateSelector
{
    public override DataTemplate
        SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement element = container as FrameworkElement;
        if (element != null && item != null)
        {
            if (item is InstallationManifesFile)
                return
                        element.FindResource("FileKey")
                        as DataTemplate;
            else if (item is InstallationManifestHook)
                return element.FindResource("HookKey")
                        as DataTemplate;
        }
        return null;
    }
}
public class CompositeCollectionConverter : IMultiValueConverter
{
    public object Convert(object[] values
        , Type targetType
        , object parameter
        , System.Globalization.CultureInfo culture)
    {
        var res = new CompositeCollection();
        foreach (var item in values)
            if (item is IEnumerable && item != null)
                res.Add(new CollectionContainer()
                {
                    Collection = item as IEnumerable
                });
        return res;
    }
    public object[] ConvertBack(object value
        , Type[] targetTypes
        , object parameter
        , System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}