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

时间:2013-09-25 12:56:13

标签: c# wpf xaml

this excellent answer上构建详细说明如何将树视图呈现并绑定到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中属性名称的知识?

您如何声明HierarchicalDataTemplates,因为在运行之前节点的深度是未知的?

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

有人可以提出一个如何实现这一目标的例子吗?

1 个答案:

答案 0 :(得分:2)

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

<强>的Xaml

<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>

代码隐藏(替代ViewModel品尝)

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;
        }
    }