如何通过值查找 TreeView 节点

发布于 2024-11-07 07:44:39 字数 895 浏览 0 评论 0原文

我正在开发一个家谱应用程序,并且计划将每个家庭成员的引用存储在 XML 文档中。我想阅读此文档并将其在我的应用程序中显示为树视图,然后使用它在应用程序的其他位置显示家庭成员。我需要做的是在节点树中找到一个特定的值(每个成员都有一个唯一的值)。我如何找到这个值?您能帮我一下吗,我对节点编辑很陌生。 TY。

顺便说一句,下面是我的 XAML 代码:

        <HierarchicalDataTemplate x:Key="NodeTemplate">
        <HierarchicalDataTemplate.ItemsSource>
            <Binding XPath="child::*" />
        </HierarchicalDataTemplate.ItemsSource>
        <TextBlock Text="{Binding Path=Name}" />
    </HierarchicalDataTemplate>
    <XmlDataProvider x:Key="xmlDataProvider"></XmlDataProvider>
</Window.Resources>
<Grid>
    <TreeView Margin="0,24,0,143"
              Name="treeView1"
              Background="AliceBlue"
              ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}"
              ItemTemplate= "{StaticResource NodeTemplate}"/>

I am working on a genealogy application and I plan to store references to each family member in an XML document. I would like to read this document and display it as a treeview in my application and then use it to display a family member elsewhere in the application. What I need to do is find a specific value in the node tree (each member will have a unique value). How would I find this value? Could you please give me a hand here, I am quite new to node editing. TY.

BTW, below is my XAML code:

        <HierarchicalDataTemplate x:Key="NodeTemplate">
        <HierarchicalDataTemplate.ItemsSource>
            <Binding XPath="child::*" />
        </HierarchicalDataTemplate.ItemsSource>
        <TextBlock Text="{Binding Path=Name}" />
    </HierarchicalDataTemplate>
    <XmlDataProvider x:Key="xmlDataProvider"></XmlDataProvider>
</Window.Resources>
<Grid>
    <TreeView Margin="0,24,0,143"
              Name="treeView1"
              Background="AliceBlue"
              ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}"
              ItemTemplate= "{StaticResource NodeTemplate}"/>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红颜悴 2024-11-14 07:44:39

我假设唯一值是 id 属性。因此,代码将如下所示:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var item = FindItemById(treeView1.Items.Cast<XmlElement>(), "2.1");
        if (item != null)
        {
            //Do something...
            //for example, item.SetAttribute("name", "test");

            //But this code will not work if the item isn't visible
            //var container = treeView1.ItemContainerGenerator.ContainerFromItem(item);
        }
    }

    public XmlElement FindItemById(IEnumerable<XmlElement> items, string id)
    {
        foreach (var item in items)
        {
            if (item.HasAttribute("id") && item.GetAttribute("id") == id)
                return item;
            var childItemsResult = FindItemById(item.ChildNodes.Cast<XmlElement>(), id);
            if (childItemsResult != null)
                return childItemsResult;
        }

        return null;      
    }

如果您的 xml 文件具有不同的属性作为标识符,请相应地更改此行: item.HasAttribute("id") && item.GetAttribute("id")

最终结果将是 XmlElement 对象。但由于树视图项的生成算法,检索容器并不容易。无论如何,如果您有具体问题 - 我可以帮助构建正确的架构。

I've assumed that the unique value is the id attribute. So the code will look so:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var item = FindItemById(treeView1.Items.Cast<XmlElement>(), "2.1");
        if (item != null)
        {
            //Do something...
            //for example, item.SetAttribute("name", "test");

            //But this code will not work if the item isn't visible
            //var container = treeView1.ItemContainerGenerator.ContainerFromItem(item);
        }
    }

    public XmlElement FindItemById(IEnumerable<XmlElement> items, string id)
    {
        foreach (var item in items)
        {
            if (item.HasAttribute("id") && item.GetAttribute("id") == id)
                return item;
            var childItemsResult = FindItemById(item.ChildNodes.Cast<XmlElement>(), id);
            if (childItemsResult != null)
                return childItemsResult;
        }

        return null;      
    }

If your xml file has a different attribute as an identifier, change this line accordingly: item.HasAttribute("id") && item.GetAttribute("id").

The final result will be the XmlElement object. But it isn't easy to retrieve the container because of the algorithm of generation of treeview items. Anyway, if you have a specific question - I can help to build a correct architecture.

生活了然无味 2024-11-14 07:44:39

将可选择的 ItemsControl 绑定到 XmlDataProvider 时,SelectedItem 包含作为该项目的绑定源的 XmlNode 。如果将其设置为视图的 DataContext,则可以显示(或编辑)可以通过 XPath 从该节点选择的任何内容。

因此,在下面的示例中(您可以将其粘贴到 Kaxaml 中),ContentControlDataContext 绑定到 TreeView 上的 SelectedItem。然后,放置在其中的控件可以绑定到可通过 XPath 找到的任何 XML 节点。

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>
    <XmlDataProvider x:Key="Data" XPath="/Data">
      <x:XData>
        <Data xmlns="">
          <Person Name="Becky">
            <Person Name="Stephen">
              <Person Name="Tom"/>
              <Person Name="Susannah"/>
            </Person>
            <Person Name="Deborah">
              <Person Name="Geoffrey"/>
              <Person Name="Christopher"/>
            </Person>
          </Person>
        </Data>
      </x:XData>
    </XmlDataProvider>
  </Page.Resources>
  <Grid> 
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TreeView x:Name="MyTreeView" ItemsSource="{Binding Source={StaticResource Data}, XPath=*}">
      <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding XPath=*}">
          <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
      </TreeView.ItemTemplate>
    </TreeView>
    <ContentControl Grid.Column="1" DataContext="{Binding ElementName=MyTreeView, Path=SelectedItem}">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition/>
          <RowDefinition/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0">Parent:</Label>
        <Label Grid.Row="1">Children:</Label>

        <Label Grid.Column="1" Content="{Binding XPath=@Name}"/>
        <ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding XPath=*}">
          <ListBox.ItemTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding XPath=@Name}"/>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
      </Grid>
    </ContentControl>
  </Grid>
</Page>

您必须使用 ContentControl 并设置 DataContext。这是这里唯一真正的技巧。您必须这样做的原因是:如果您尝试仅绑定 TextBlock,比如说,您最终会得到如下控件:

<TextBlock Text="{Binding ElementName=MyTreeView, Path=SelectedItem, XPath=@Name}"/>

并且您不能使用 PathXPath 在同一绑定中。

When you bind a selectable ItemsControl to an XmlDataProvider, the SelectedItem contains the XmlNode that's the binding source for the item. If you set that as the DataContext for a view, you can then display (or edit) anything that can be selected via XPath from that node.

So in the below example, which you can paste into Kaxaml, the ContentControl's DataContext is bound to the SelectedItem on the TreeView. Controls placed inside it can then bind to any XML nodes that are findable via XPath.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>
    <XmlDataProvider x:Key="Data" XPath="/Data">
      <x:XData>
        <Data xmlns="">
          <Person Name="Becky">
            <Person Name="Stephen">
              <Person Name="Tom"/>
              <Person Name="Susannah"/>
            </Person>
            <Person Name="Deborah">
              <Person Name="Geoffrey"/>
              <Person Name="Christopher"/>
            </Person>
          </Person>
        </Data>
      </x:XData>
    </XmlDataProvider>
  </Page.Resources>
  <Grid> 
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <TreeView x:Name="MyTreeView" ItemsSource="{Binding Source={StaticResource Data}, XPath=*}">
      <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding XPath=*}">
          <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
      </TreeView.ItemTemplate>
    </TreeView>
    <ContentControl Grid.Column="1" DataContext="{Binding ElementName=MyTreeView, Path=SelectedItem}">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition/>
          <RowDefinition/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0">Parent:</Label>
        <Label Grid.Row="1">Children:</Label>

        <Label Grid.Column="1" Content="{Binding XPath=@Name}"/>
        <ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding XPath=*}">
          <ListBox.ItemTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding XPath=@Name}"/>
            </DataTemplate>
          </ListBox.ItemTemplate>
        </ListBox>
      </Grid>
    </ContentControl>
  </Grid>
</Page>

You have to use a ContentControl and set the DataContext. That's the only actual trick here. The reason you have to do this: if you tried to just bind a TextBlock, say, you'd end up with a control like:

<TextBlock Text="{Binding ElementName=MyTreeView, Path=SelectedItem, XPath=@Name}"/>

and you can't use Path and XPath in the same binding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文