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

时间:2013-08-29 17:41:56

标签: c# wpf treeview

我正在尝试使用以下层次结构创建TreeView:

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

基本上,根级节点是一个子节点为File and 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;
   }
}

我只能在HierarchicalDataTemplate的ItemTemplate中添加一个Datatemplate。如何在单个HierarchicalDataTemplate下指定两种数据类型?

2 个答案:

答案 0 :(得分:0)

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

的转换器

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

由于

答案 1 :(得分:0)

我尝试使用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();
    }
}