WPF树中的层次数据模板问题

WPF树中的层次数据模板问题,wpf,Wpf,我有一个WPF树,它需要显示一些节点。假设我有两种类型的实体,EntityA和EntityB。这两个实体都实现了一个通用接口。现在,EntityA将拥有EntityB元素和EntityA元素的集合。如何通过HierarchycalDataTemplate显示此内容 我在VM中公开了一个名为“DisplayItems”的ObservableCollection(),它将包含EntityA类型的元素 EnittyA和EntityB都将有另一个称为“ItemCollection”的Observable

我有一个WPF树,它需要显示一些节点。假设我有两种类型的实体,EntityA和EntityB。这两个实体都实现了一个通用接口。现在,EntityA将拥有EntityB元素和EntityA元素的集合。如何通过HierarchycalDataTemplate显示此内容

我在VM中公开了一个名为“DisplayItems”的ObservableCollection(),它将包含EntityA类型的元素

EnittyA和EntityB都将有另一个称为“ItemCollection”的ObservableCollection。对于EntityA,ItemCollection列表理想情况下应该包含EntityA和EntityB类型的实体

我使用的当前HierarchycalDataTemplate和XAML如下所示:

 <HierarchicalDataTemplate ItemsSource="{Binding Path=ItemCollection}" DataType="{x:Type Entities:EntityB}">
      <Grid>
        <StackPanel Orientation="Horizontal" x:Name="compositeCT">
          <Image Source="/Images/EntityB.png" Width="15" Height="15"/>
          <Label Foreground="Blue" Content="{Binding Path=Name}"/>
          <Label Foreground="Black" Content=" = "/>
          <Label Foreground="Blue" Content="{Binding Path=CompositeLabel}"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" x:Name="nCompositeCT">
          <Image Source="/Images/EntityB.png" Width="15" Height="15"/>
          <TextBlock Foreground="Blue" Text="{Binding Path=Name}"/>
        </StackPanel>
 <HierarchicalDataTemplate.ItemTemplate>
        <DataTemplate>
          <TextBlock Foreground="Green" Text="{Binding}"/>
        </DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>

 <HierarchicalDataTemplate ItemsSource="{Binding Path=ItemCollection}" DataType="{x:Type Entities:EntityA}">
      <StackPanel Orientation="Horizontal" >
        <Image Source="/Images/ElementA.png" Margin="3" Width="15" Height="15" Focusable="False"/>
        <TextBlock Foreground="Red" Text="{Binding Path = Name}" Focusable="False"/>
      </StackPanel>
    </HierarchicalDataTemplate>

<TreeView x:Name="tvMyTree"
            ItemsSource="{Binding DisplayItems}"
            AllowDrop="True"         
            VirtualizingStackPanel.IsVirtualizing="True" 
            VirtualizingStackPanel.VirtualizationMode="Recycling" 
            ScrollViewer.IsDeferredScrollingEnabled="True"
            Margin="5"
            TreeViewItem.Expanded="OnTreeViewItemExpanded"
            TreeViewItem.Selected="OnTreeViewItemSelected" 
         />

您可以定义两个Hierarchy-CalDataTemplates,这很好。在TextBlock的位置上,您可以根据EntityA和EntityB的其他属性放置所需的任何复杂可视化

        <HierarchicalDataTemplate  DataType="{x:Type local:EnittyA}" ItemsSource="{Binding ItemCollection}" >
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate  DataType="{x:Type local:EnittyB}" ItemsSource="{Binding ItemCollection}" >
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>

我认为ItemTemplateSelector非常适合您的要求。ItemTemplateSelector是继承的,所以您不应该关心模板的端点接收者。接收方(项目容器)仅将地址发送给选择器,最后一个接收方根据数据类型返回正确的模板:

public class LayoutItemTemplateSelectorItem
{
    public Type TargetType
    {
        get;
        set;
    }
    public DataTemplate Template
    {
        get;
        set;
    }
}
[ContentProperty("Items")]
public class LayoutItemTemplateSelector : DataTemplateSelector
{
    public LayoutItemTemplateSelector()
    {
        this.Items = new Collection<LayoutItemTemplateSelectorItem>();
    }
    public Collection<LayoutItemTemplateSelectorItem> Items
    {
        get;
        private set;
    }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var component = (LayoutItem)item;
        var typeToSearch = component.GetType();

        var foundItem = this.Items
            .Where(i => i.TargetType == typeToSearch)
            .FirstOrDefault();

        if (foundItem != null)
        {
            return foundItem.Template;
        }

        throw new Exception(string.Format(Properties.Resources.AppropriateTemplateNotFound, typeToSearch.FullName));
    }
}
公共类LayoutItemTemplateSelectorItem
{
公共类型TargetType
{
收到
设置
}
公共数据模板
{
收到
设置
}
}
[内容属性(“项目”)]
公共类LayoutItemTemplateSelector:DataTemplateSelector
{
public LayoutItemTemplateSelector()
{
this.Items=新集合();
}
公众收集物品
{
收到
私人设置;
}
公共覆盖数据模板SelectTemplate(对象项,DependencyObject容器)
{
var组件=(LayoutItem)项;
var typeToSearch=component.GetType();
var foundItem=this.Items
.其中(i=>i.TargetType==typeToSearch)
.FirstOrDefault();
if(foundItem!=null)
{
返回foundItem.Template;
}
抛出新异常(string.Format(Properties.Resources.properteTemplateNotFound,typeToSearch.FullName));
}
}
XAML中的用法:

<UserControl ...>
    <UserControl.Resources>
        <ResourceDictionary>

            <HierarchicalDataTemplate  x:Key="EntityBTemplate" 
                                       ItemsSource="{Binding Path=ItemCollection}"
                                       DataType="{x:Type Entities:EntityB}">
                ...
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate x:Key="EntityATemplate" 
                                      ItemsSource="{Binding Path=ItemCollection}"
                                      DataType="{x:Type Entities:EntityA}">
                ...
            </HierarchicalDataTemplate>

            <LayoutItemTemplateSelector x:Key="TemplateSelector">
                <LayoutItemTemplateSelectorItem TargetType="{x:Type EntityA}"
                                                Template="{StaticResource EntityATemplate}"/>
                <LayoutItemTemplateSelectorItem TargetType="{x:Type EntityB}"
                                                Template="{StaticResource EntityBTemplate}"/>
            </LayoutItemTemplateSelector>
        </ResourceDictionary>
    </UserControl.Resources>
<Grid>
    <TreeView ItemsSource="{Binding DisplayItems}"
              ItemTemplateSelector="{StaticResource TemplateSelector}"/>
</Grid>
</UserControl>

...
...

看起来您的xaml代码没有正确粘贴