TreeView不显示对象层次结构
我在使用对象数据绑定创建 WPF TreeView 时遇到了一些严重的问题。
该应用程序是配置文件编辑器。我定义了一个可以序列化为正确 XML 格式的对象结构。
我遇到的问题是格式化 TreeView 中显示正确层次结构的对象实例。 TreeView 只会渲染 Channel 节点,不会渲染其他任何东西。
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; }
}
Channel
的所有子类都包含属性 Id
和 Name
。 Filters 类是具有相同属性定义的其他类型的集合。
XAML
<Window.Resources>
<ObjectDataProvider x:Key="data"/>
<DataTemplate DataType="{x:Type ConfigurationEditor:Channel}">
<WrapPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
<TextBlock Text=" [" />
<TextBlock Text="{Binding Path=Id}" />
<TextBlock Text="]" />
</WrapPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<TreeView Margin="12,12,12,96" Name="treeView1" ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
</TreeView>
</Grid>
这是创建数据实例的
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>
TreeView
没有变化。经过此更改,我仍然只列出了 Channel
,而没有其他内容。
I am having some serious trouble creating a WPF TreeView with an Object databinding.
The application is config file editor. I have defined an Object structure which can be serialized to the correct XML format.
The problem I am having is formatting the object instance in the TreeView showing the correct hierarchy. The TreeView will only render the Channel node, and nothing else.
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; }
}
All the child classes of Channel
contain properties Id
and Name
. The Filters class is a collection of other types with the same property definition.
Here is the XAML
<Window.Resources>
<ObjectDataProvider x:Key="data"/>
<DataTemplate DataType="{x:Type ConfigurationEditor:Channel}">
<WrapPanel>
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
<TextBlock Text=" [" />
<TextBlock Text="{Binding Path=Id}" />
<TextBlock Text="]" />
</WrapPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<TreeView Margin="12,12,12,96" Name="treeView1" ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
</TreeView>
</Grid>
The code behind to create the data instance
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;
I've looked at countless examples but I still can figure out what I am doing wrong. Thanks for the help.
Update:
<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>
No change to the TreeView
. With this change I still have only the Channel
listed, and nothing else.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
扩展@Gimalay的答案,问题是 TreeView 不知道从哪里获取任何子节点的数据。您可以使用
HierarchialDataTemplate
而不是DataTemplate
通知TreeView
:两者之间的主要区别在于
ItemsSource
> 属性。这是一个绑定表达式,它返回用作子节点的对象集合。问题是你有几处房产可以生孩子,而不仅仅是一处。您要么需要将它们全部组合到一个属性中,要么添加另一个返回所有子节点的属性。
最后,您需要为每个子项类型定义一个
DataTemplate
,以便TreeView
知道如何显示它们(您可以使用HierarchialDataTemplate
code> 也适用于子节点,如果它们又具有子节点)。Expanding on @Gimalay's answer, the problem is that the
TreeView
doesn't know where to get the data for any child nodes. You inform theTreeView
by using aHierarchialDataTemplate
, rather than aDataTemplate
:The main difference between the two is the
ItemsSource
attribute. This is a binding expression that returns a collection of objects to use as child nodes.The problem is that you have a few properties to get children from, not just one. You either need to combine them all into one property, or add another property that returns all of the child nodes.
Finally, you'll need to define a
DataTemplate
for each child item type, so that theTreeView
knows how to display them (you can use aHierarchialDataTemplate
for the children as well, if they in turn have child nodes).我认为您不需要这个模板,因为对象永远不会出现在 TreeView 的图片中。
您已在 XAML 中设置了此设置,它显示了通道..完美!
现在您还希望显示 Reader。 但是只能将 IEnumerable 类型的对象指定为 ItemsSource,因此下面的模板将“Reader”指定为 ItemsSource 是不正确的。
因此,如果您还希望显示读者姓名,请使用如下所示的模板。
I don't think you need this template, as Objects never come in the picture in your TreeView.
You have set this in XAML, which shows the Channels.. perfect!
Now you want the Reader to be shown as well. But one can only specify objects of type IEnumerable as an ItemsSource, so the template below is incorrect which specifies "Reader" as the ItemsSource.
So if you want reader name to be shown as well, use the template as shown below.
正是为了这个目的,当项目源本身内部实际上具有层次结构时,才会使用层次结构数据模板。也就是说,对象本身具有一定的层次结构,父对象保留子对象的列表。
作为示例,每个 Channel 可能都有一个属性 SubChannels,如下所示。
那么我们就可以使用这样的模板。
现在,对象结构可以是多级深度的,每个子通道又具有子通道。
另外,请注意,在示例中,我只是使用相同的类型 Channel 来创建子通道的层次结构。我们可以使用另一种类型,假设每个频道都有一个读者列表。
Just for the sake of it, hierarchical data templates are used when the items source actually has a hierarchy within itself. That is, the objects themselves have some hierarchy, with parent objects keeping a list of child objects.
As an example, may be the each Channel has a property SubChannels like below.
Then we could have used a template like this.
Now the object structure could be multilevel deep with each subchannel again having subchannels.
Also, do note that in the example I just used the same type, Channel, to create a hierarchy of subchannels. We could have used another type, say each Channel having a list of readers.
好吧,经过多次尝试错误后,我能够让它按我想要的方式工作。我是这样做的。
在我的 Channel 对象中,我添加了一个新属性,它是我想要在 TreeView 中显示的所有其他属性的集合,
然后我的 XAML 如下所示,用于显示树视图。
感谢安迪让我走上正轨。
Okay, After much trial an error I was able to get this to work as I wanted. Here is how i did it.
In my
Channel
object I added a new property that was a collection of all the other properties which I wanted to display in the TreeViewThen my XAML is as follows to display the treeview.
Thanks Andy for putting me on the right track.