C# TreeView不显示对象层次结构

C# TreeView不显示对象层次结构,c#,.net,wpf,treeview,objectdataprovider,C#,.net,Wpf,Treeview,Objectdataprovider,我在创建带有对象数据绑定的WPF树视图时遇到了一些严重的问题 应用程序是配置文件编辑器。我定义了一个可以序列化为正确XML格式的对象结构 我遇到的问题是在树视图中格式化对象实例,以显示正确的层次结构。TreeView将只渲染通道节点,而不渲染其他内容 public class Objects { public List<Channel> Channels { get; set; } } public class Channel { public string Id

我在创建带有对象数据绑定的WPF树视图时遇到了一些严重的问题

应用程序是配置文件编辑器。我定义了一个可以序列化为正确XML格式的对象结构

我遇到的问题是在树视图中格式化对象实例,以显示正确的层次结构。TreeView将只渲染通道节点,而不渲染其他内容

public class Objects
{
    public List<Channel> Channels { get; set; }
}

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public Reader Reader { get; set; }
    public Filters Filters { get; set; }
    public Router Router { get; set; }
    public Persister Persister { get; set; }
}

public class Filters : ArrayList
{
    public string StopOnFailure { get; set; }
}

public class Reader
{
    public string Id { get; set; }
    public string Name { get; set; }
}
用于创建数据实例的代码

Objects config;
var serializer = new XmlSerializer(typeof(Objects));
using (var stream = new FileStream(@"C:\test.xml", FileMode.Open))
{
    config = (Objects)serializer.Deserialize(stream);
}

var dp = (ObjectDataProvider)FindResource("data");
dp.ObjectInstance = config;
我已经看过无数的例子,但我仍然可以找出我做错了什么。谢谢你的帮助

更新:

<HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Objects}" ItemsSource="{Binding Path=Channels}"/>
<HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Channel}" ItemsSource="Binding Path=Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

<DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>


无需更改
树视图
。通过此更改,我仍然只列出了
频道,没有其他内容。

扩展@Gimalay的答案,问题是
树视图不知道从何处获取任何子节点的数据。通过使用
层次数据模板而不是
数据模板来通知
树视图

public class Objects
{
    public List<Channel> Channels { get; set; }
}

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public Reader Reader { get; set; }
    public Filters Filters { get; set; }
    public Router Router { get; set; }
    public Persister Persister { get; set; }
}

public class Filters : ArrayList
{
    public string StopOnFailure { get; set; }
}

public class Reader
{
    public string Id { get; set; }
    public string Name { get; set; }
}
<HierarchialDataTemplate DataType="{x:Type ConfigurationEditor:Channel}"
    ItemsSource="...">
    <WrapPanel>
        <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
        <TextBlock Text=" [" />
        <TextBlock  Text="{Binding Path=Id}" />
        <TextBlock Text="]" />
    </WrapPanel>
</HierarchialDataTemplate>

两者之间的主要区别在于
itemsource
属性。这是一个绑定表达式,返回用作子节点的对象集合

问题是您有几个属性可以从中获取子对象,而不仅仅是一个。您需要将它们全部合并到一个属性中,或者添加另一个返回所有子节点的属性


最后,您需要为每个子项类型定义一个
DataTemplate
,以便
TreeView
知道如何显示它们(如果子项又有子节点,您也可以使用
hierarcialdatatemplate
),因为对象永远不会出现在树视图的图片中

<HierarchicalDataTemplate
    DataType="{x:Type ConfigurationEditor:Objects}" 
    ItemsSource="{Binding Path=Channels}"/>

您已经在XAML中进行了设置,其中显示了通道。。太好了

<TreeView 
    Margin="12,12,12,96" Name="treeView1" 
    ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
</TreeView>

现在,您希望也显示阅读器但只能将IEnumerable类型的对象指定为ItemsSource,因此下面的模板不正确,该模板将“Reader”指定为ItemsSource

<HierarchicalDataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" 
    ItemsSource="{Binding Path=Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

因此,如果您希望同时显示阅读器名称,请使用如下所示的模板

<DataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" >
    <StackPanel>
        <TextBlock Text="{Binding Path=Name}"/>
        <TextBlock Text="{Binding Path=Reader.Name}"/>
    <StackPanel>
</DataTemplate>

仅为方便起见,当项目源本身实际上具有层次结构时,就使用层次结构数据模板。也就是说,对象本身具有某种层次结构,父对象保留子对象的列表

例如,可能是每个通道都具有如下所示的属性子通道

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public ObservableCollection<Channel> SubChannels { get; }
}
公共类频道
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
公共可观测收集子通道{get;}
}
然后我们可以使用这样的模板

<HierarchicalDataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" 
    ItemsSource="{Binding Path=SubChannels}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

现在,对象结构可以是多层次的,每个子通道都有子通道


另外,请注意,在示例中,我刚刚使用了相同的类型Channel来创建子通道的层次结构。我们可以使用另一种类型,比如说每个频道都有一个读卡器列表。

好的,经过多次尝试,一个错误,我能够让它按我想要的方式工作。我是这样做的

在我的
频道
对象中,我添加了一个新属性,它是我想在树视图中显示的所有其他属性的集合

public ArrayList Components
{
    get { return new ArrayList { Reader, Filters, Router, Persister  }; } 
    set
    {
        ArrayList list = value;
        if (list != null)
        {
            foreach (var item in list)
            {
                if (item is Reader)
                {
                    Reader = (Reader)item;
                }
                else if (item is Router)
                {
                    Router = (Router) item;
                }
                else if (item is Persister)
                {
                    Persister = (Persister) item;
                }
                else if (item is Filters)
                {
                    Filters = (Filters) item;
                }
            }
        }
    }
}
然后我的XAML如下所示来显示treeview

    <HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Channel}" ItemsSource="{Binding Path=Components}">
        <WrapPanel>
            <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
            <TextBlock Text=" [" />
            <TextBlock  Text="{Binding Path=Id}" />
            <TextBlock Text="]" />
        </WrapPanel>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Filters}" ItemsSource="{Binding Path=.}">
        <TextBlock Text="Filters"/>
        <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate >
                <TextBlock Text="{Binding Path=Name}"/>
            </DataTemplate>
        </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Router}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Persister}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>


谢谢安迪让我走上正轨。

有点吹毛求疵,但请在你的帖子中将“WCF”改为“WPF”。WCF和WPF是独立的技术。@David:我修复了它以避免混淆。
对象
类有一个包含
频道
对象集合的属性。因此,我使用该类型和属性创建了一个
hierarchicalDataTemplate
。然后,我可以通过添加另一个模板来显示
频道
节点,但是叶节点仍然没有显示。您可以发布更新的代码吗?这可能有助于调试问题。谢谢你的评论,这很有帮助,但不是我想要达到的效果。最终,我希望将
通道
对象复制为树。这意味着
频道的所有属性在树视图中显示为子节点。在您给出的示例中,
读取器
名称显示在与
频道
相同的级别。从你下面的评论来看,我想做的似乎不可能。