在WPF应用程序中使用TreeView控件显示XML文件数据

在本文中,将探讨如何使用WPF应用程序中的TreeView控件来显示一个简单XML文件中的数据,而无需编写任何代码。所有的关键操作都在定义窗口内容的XAML文件中完成。虽然可能不会尝试用这种方式编写商业应用程序,但这里可能会有一些知识可以帮助更容易地构建商业应用程序。

本文基于两篇关于使用WPF和XML的文章的信息。第一篇是Josh Smith的《对简单WPF资源管理器树的反馈》,在这篇文章中,Smith展示了如何使用DataTemplate定义TreeViewItem的内容,以及如何使用窗口的“Loaded”事件处理程序构建树结构。第二篇文章是Karl Shifflett的《对简单WPF资源管理器树的过度反应》,Shifflett的文章描述了HierarchicalDataTemplate,展示了它如何帮助递归树结构数据来填充TreeView控件。

在寻找一种解决方案来填充TreeView,显示类似于Windows资源管理器的目录树,包括至少一些文件名时,遇到了TreeView的奇怪行为,并决定使用XML数据进行一些测试。这本身就是一个挑战,但是通过从Shifflett和Smith的文章中获取信息,以及一些思考,找到了下面描述的解决方案,使用XML数据填充TreeView控件。

使用代码

实际上,使用WPF显示XML数据相当容易。除了XML文件本身,几乎所有的工作都在XAML中完成,大部分是通过定义几个资源来完成的。本文附带的源代码是一个完整的工作示例。项目配置为使用.NET 4.0,但可以将MainWindow.xaml和testdata.xml移动到WPF 3.0项目中,它应该同样有效。

在下面的文本中,将只突出显示使这成为可能的XAML代码的示例。

当创建一个WPF项目时,会在一个名为MainWindow.xaml的文件中创建一个骨架窗口,该文件在Visual Studio编辑器中打开。包括一些XAML来配置默认窗口,使用Grid控件来容纳窗口的其余视觉元素。在代码中,在Window元素的开头,Grid标签之前,添加了一个新的子元素,并在Window标签下方,创建了一个在Window内定义一些资源的部分。

资源部分最初看起来像这样:

<Window.Resources> </Window.Resources>

然后在这些Window.Resources标签之间,添加了几个将被UI用来显示XML数据的元素。添加的第一个资源是XmlDataProvider。XmlDataProvider是一个类,它使得将XML数据绑定到元素并使用XML结构成为可能。通过像这样创建一个资源来创建一个对象:

<XmlDataProvider x:Key="xmldata" Source="testdata.xml" XPath="/root" />

Source属性设置为为测试创建的XML文件的名称,但实际上在运行时并不引用文件。通过将文件放在项目的根目录中,并将构建操作设置为"Resource",文件的内容实际上在编译时成为程序集的一部分。因此,在这种情况下,文件名成为资源的键名称,WPF足够智能,可以在应用程序运行时计算出细节。XPath属性用于指定一个节点。XML测试文件有一个名为"root"的根节点,所以在这里使用它来开始XML解析。

有趣的工作是在数据模板中完成的,这些模板是使用HierarchicalDataTemplate创建的。再次,在Window.Resources元素内,紧接XmlDataProvider之后,为XML测试文件中使用的每种类型的标签创建一个数据模板。在这种情况下,testdata.xml中存在三个节点项,"root"、"Node"和"leaf"。所以创建了三个数据模板。"Node"的模板看起来像这样:

<HierarchicalDataTemplate DataType="Node" ItemsSource="{Binding XPath=./*}"> <StackPanel Orientation="Horizontal"> <TextBlock Margin="0" Text="Node:" /> <TextBlock Margin="5,0,0,0" Text="{Binding XPath=@name}" /> </StackPanel> </HierarchicalDataTemplate>

其他模板类似。需要注意的主要区别是,没有为"leaf"节点指定ItemsSource属性,因为知道没有在"leaf"节点中放置任何项目。这样的节点总是在行的末端,所以没有必要检查它们是否包含内容。ItemsSource属性由HierarchicalDataTemplate特别为此用途提供。

HierarchicalDataTemplate使用ItemsSource来确定当前项是否包含其他项。如果没有,节点将相应地呈现,并且无法进一步导航到节点中。但如果当前项包含其他项,它将被渲染,以便用户可以钻取到节点中查看其他项。

通过设置Grid的DataContext和TreeView控件的ItemsSource属性来绑定XML数据到UI控件。完整的UI定义在几行内完成。

<Grid DataContext="{StaticResource xmldata}"> <TreeView Name="dirTree" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding}" VirtualizingStackPanel.IsVirtualizing="False" VirtualizingStackPanel.VirtualizationMode="Standard" /> </Grid>

就是这样!

感兴趣的点

HierarchicalDataTemplate类使得使用TreeView填充XML数据变得非常容易。没有理由它不能在其他场景中使用,以帮助更复杂的情况。要记住的主要事情是为TreeView预期的每种类型创建一个模板(或者为父类型创建一个模板,以捕获几种派生类型),并在可能包含更多需要进入TreeView的数据的类型上设置ItemsSource。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485