C# TreeView不显示对象层次结构
我在创建带有对象数据绑定的WPF树视图时遇到了一些严重的问题 应用程序是配置文件编辑器。我定义了一个可以序列化为正确XML格式的对象结构 我遇到的问题是在树视图中格式化对象实例,以显示正确的层次结构。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
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
。然后,我可以通过添加另一个模板来显示频道
节点,但是叶节点仍然没有显示。您可以发布更新的代码吗?这可能有助于调试问题。谢谢你的评论,这很有帮助,但不是我想要达到的效果。最终,我希望将通道
对象复制为树。这意味着频道的所有属性在树视图中显示为子节点。在您给出的示例中,读取器
名称显示在与频道
相同的级别。从你下面的评论来看,我想做的似乎不可能。