65.9K
CodeProject 正在变化。 阅读更多。
Home

在 WPF TreeView 中显示 XML

starIconstarIconstarIconstarIconstarIcon

5.00/5 (8投票s)

2012 年 1 月 23 日

CPOL

5分钟阅读

viewsIcon

92463

downloadIcon

9290

在本文中,我将介绍如何在 WPF TreeView 控件中显示来自简单 XML 文件的数据。

引言

在本文中,我将介绍如何在 WPF 应用程序中使用 TreeView 控件显示简单 XML 文件中包含的数据,而无需编写任何代码。在本文中,所有的魔力都体现在定义窗口内容的 XAML 文件中。不可否认,你不会尝试像这样编写业务应用程序,但其中可能有一些东西可以让你更容易地完成该业务应用程序。

背景

本文借鉴了另外两篇关于 WPF 与 XML 使用的文章,你可能想阅读一下。第一篇是 Josh Smith 的 Reaction to: A Simple WPF Explorer Tree。在这篇文章中,Smith 演示了如何使用 DataTemplate 定义 TreeViewItem 的内容,以及如何使用窗口的“Loaded”事件处理程序构建树结构。Karl Shifflett 的第二篇文章是基于 Smith 的文章。Shifflett 的文章名为 Over Reaction To: A Simple WPF Explorer Tree。Shifflett 的文章描述了 HierarchicalDataTemplate,演示了如何使用它来递归处理树结构数据以填充 TreeView 控件。

我在尝试找到一种解决方案来用目录和文件名填充 TreeView,使其类似于 Window Explorer 的目录树,但同时包含至少一些文件名。在解决这个问题的过程中,我遇到了 TreeView 中的一些奇怪的行为,于是决定用 XML 数据进行一些测试。这本身就有点挑战,但通过从 Shifflett 和 Smith 的文章中获取信息,并稍加运用,我提出了下面描述的解决方案,用于用 XML 数据填充 TreeView 控件。

Using the Code

实际上,使用 WPF 显示 XML 数据非常容易。除了 XML 文件本身,几乎所有实现这一功能的工作都在 XAML 中完成,其中大部分是通过定义几个资源来完成的。本文提供的源代码是一个完整的可运行示例。该项目配置为使用 .NET 4.0,但你可以将 MainWindow.xamltestdata.xml 移到一个 WPF 3.0 项目中,它应该也能正常工作。

在下面的文本中,我将重点介绍使此功能工作的 XAML 代码样本。

当你创建一个 WPF 项目时,一个骨架窗口会以一个名为 MainWindow.xaml 的文件创建,该文件在 Visual Studio 编辑器中打开。包含少量 XAML 代码以配置默认窗口,其中包含一个 Grid 控件来容纳窗口的其余视觉元素。在我们的代码中,我们在打开 Grid 标签之前、Window 标签的下方,向 Window 元素添加一个新的子元素,以在 Window 中创建一个区域来定义一些资源。起初,资源区域看起来像这样:

<!-- This goes immediately after the opening Window tag -->
<Window.Resources>
</Window.Resources>

然后,在 Window.Resources 标签之间,我们添加了几个将由 UI 用于显示 XML 数据并将 XML 数据绑定的元素。我们添加的第一个资源是 XmlDataProviderXmlDataProvider 是一个类,它使得能够将 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 来确定当前项是否包含其他项。如果不是,则节点将相应地呈现,并且无法进一步导航到节点中。但是,如果当前项包含其他项,则会呈现该节点,以便用户可以钻取到节点中以查看其他项。

最后要做的是将 XML 数据绑定到 UI 控件。我通过设置 GridDataContextTreeView 控件的 ItemsSource 属性来完成此操作。完整的 UI 在短短几行内定义。

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

就是这样!

关注点

HierarchicalDataTemplate 类使得使用 XML 数据填充 TreeView 非常容易。它也可以用于其他场景,以帮助处理更复杂的情况。需要记住的主要事项是为 TreeView 期望的每种类型创建模板(或者是一个父类型来捕获几个子类型),并为可能包含需要放入 TreeView 的更多数据的类型设置 ItemsSource

历史

  • 2012 年 1 月 20 日 - 原始文章。
  • 2012 年 1 月 21 日 - 对代码对齐进行的化妆品级更改。
© . All rights reserved.