将 xml 文档动态绑定到树视图

本文关键字:视图 动态绑定 xml 文档 | 更新日期: 2023-09-27 18:32:41

在这个详细介绍如何将树视图呈现和绑定到 xml 文档的出色答案的基础上,我想知道是否有人可以提供一种方法来使其更通用,以便它可以接受任何有效的 xml。

        <HierarchicalDataTemplate x:Key="colorsTemplate">
            <TextBox Text="{Binding XPath=@Name, Mode=TwoWay}" />
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate x:Key="rootTemplate" ItemsSource="{Binding XPath=FavoriteColors/Color}" ItemTemplate="{StaticResource colorsTemplate}">
            <StackPanel Orientation="Horizontal">
                <TextBox Text="{Binding XPath=@FirstName, Mode=TwoWay}" />
                <TextBlock Text=" " />
                <TextBox Text="{Binding XPath=@LastName, Mode=TwoWay}" />
                <TextBlock Text=" (Age: " />
                <TextBox Text="{Binding XPath=@Age, Mode=TwoWay}" />
                <TextBlock Text=")" />
            </StackPanel>
        </HierarchicalDataTemplate>

例如,假设加载按钮不是静态加载 People.xml,而是显示一个文件对话框,用户可以上传任何 xml 文件。
所以这个

private void Load_Click(object sender, RoutedEventArgs e)
{
    var xmlDocument = new XmlDocument();
    xmlDocument.Load("People.xml");
    people.Document = xmlDocument;
}

看起来更像这样

private void Load_Click(object sender, RoutedEventArgs e)
{
   var xmlDocument = new XmlDocument();
   Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
   bool? result = dlg.ShowDialog();
   if ( result == true ) {
       xmlDocument.Load(dlg.FileName);
       people.Document = xmlDocument;
   }
}

那么,如何定义绑定,这些绑定似乎依赖于从正在处理的 xml 中了解属性名称?

您将如何声明分层数据模板,因为节点的深度在运行时之前是未知的?

我的假设是模板必须构建在隐藏的代码中,但也许这是不正确的。

谁能举出一个例子来说明如何做到这一点?

将 xml 文档动态绑定到树视图

诀窍是将 XPath-Expression 更改为 child::node() 并实现一个数据触发器来区分节点和属性。

哈姆勒

<Window x:Class="XmlDataBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <HierarchicalDataTemplate x:Key="NodeTemplate">
            <TextBlock x:Name="text"
                       Text="?" />
            <HierarchicalDataTemplate.ItemsSource>
                <Binding XPath="child::node()" />
            </HierarchicalDataTemplate.ItemsSource>
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=NodeType}"
                             Value="Text">
                    <Setter TargetName="text"
                            Property="Text"
                            Value="{Binding Path=Value}"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=NodeType}"
                             Value="Element">
                    <Setter TargetName="text"
                            Property="Text"
                            Value="{Binding Path=Name}"></Setter>
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
        <XmlDataProvider x:Key="xmlDataProvider"></XmlDataProvider>
    </Window.Resources>

    <Grid>
        <TreeView Name="treeView1"
                  Background="AliceBlue"
                  ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}"
                  ItemTemplate="{StaticResource NodeTemplate}" />
    </Grid>
</Window>

代码隐藏(替换视图模型来品尝)

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent(); 
            var dataProvider = this.FindResource("xmlDataProvider") as XmlDataProvider;
            var doc = new XmlDocument();
            // Testdocument
            doc.LoadXml(
                 @"<root>
                    <child1>text1<child11>text11</child11>
                    </child1>
                    <child2>text2<child21>text21</child21>
                        <child22>text22</child22>
                    </child2>
                  </root>");
            dataProvider.Document = doc;
        }
    }