1

基于这个详细说明如何呈现树视图并将其绑定到 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?

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

任何人都可以举一个如何实现这一点的例子吗?

4

1 回答 1

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;
        }
    }
于 2013-09-25T13:18:39.987 回答