我有一个带有XmlDataProvider的TreeView的XML数据绑定。如果我向XML添加一个子节点,TreeView会显示它,但我该如何选择这个项目?
XAML:
<Window.Resources>
<HierarchicalDataTemplate DataType="category" ItemsSource="{Binding XPath=child::node()}">
<TextBlock Text="{Binding XPath=@name}" FontWeight="Bold" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="card">
<TextBlock Text="{Binding XPath=./title}" FontStyle="Italic" />
</HierarchicalDataTemplate>
<XmlDataProvider x:Key="dataxml" XPath="root/cards"/>
</Window.Resources>
<TreeView Name="treeView"
ItemsSource="{Binding Source={StaticResource dataxml},
XPath=./*,
UpdateSourceTrigger=PropertyChanged}"
/>
CS:
public partial class MainWindow : Window
{
XmlDataProvider xmlDataProvider = new XmlDataProvider();
public MainWindow()
{
InitializeComponent();
xmlDataProvider = this.FindResource("dataxml") as XmlDataProvider;
xmlDataProvider.Source = new Uri(System.IO.Path.GetFullPath(fullPathToXml), UriKind.Absolute);
xmlDataProvider.Refresh();
}
public void AddChild()
{
XmlNode newNode = xmlDataProvider.Document.CreateElement("card");
XmlNode selectedItem = (XmlNode)treeView.SelectedItem;
if (selectedItem != null)
{
//add the newNode as child to the selected
selectedItem.AppendChild(newNode);
//select the childnode (newNode) ????? <=====
}
else
{
//add the newNode as child to the rootnode and select it:
xmlDataProvider.Document.DocumentElement["cards"].AppendChild(newNode);
(treeView.ItemContainerGenerator.ContainerFromItem(newNode) as TreeViewItem).IsSelected = true;
}
xmlDataProvider.Document.Save(fullPathToXml);
xmlDataProvider.Refresh();
}
}
XML:
<root>
<settings>
....
..
</settings>
<cards>
<category name="C1">
<card name="card1">
<question>bla</question>
<answer>blub</answer>
</card>
<category name="C2">
<card name="card4">
<question>bla</question>
<answer>blub</answer>
</card>
</category>
</category>
<card name="card2">
<question>bla</question>
<answer>blub</answer>
</card>
<card name="card3">
<question>bla</question>
<answer>blub</answer>
</card>
</cards>
</root>
答案 0 :(得分:1)
此blog post介绍了如何选择项目。基本上,您不能只使用TreeView.ItemContainerGenerator,因为它只允许您访问根TreeViewItems。使用父TreeViewItem的TreeViewItem.ItemContainerGenerator访问嵌套的TreeViewItem。
答案 1 :(得分:0)
我有第一种方法:
((treeView.ItemContainerGenerator.ContainerFromIndex(1) as TreeViewItem).ItemContainerGenerator.ContainerFromItem(newNode) as TreeViewItem).IsSelected = true;
如果我将他添加到位置1的类别,则选择newNode,否则我成为例外; - )
现在我处理一个具有多个级别的动态: - )
答案 2 :(得分:0)
已经很晚了,所以我的功能不是最顺畅的,但它确实有效! 我曾经对所有曾经有同样问题的人发表评论; - )
Usings:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Xml;
using System.Runtime.InteropServices;
功能:
/// <summary>
/// Select a XmlNode in a TreeView that is databound to a xmlDataProvider.
/// </summary>
/// <param name="treeView">A referenz to the TreeView.</param>
/// <param name="node">The node to select.</param>
public static void SelectTreeViewNode(ref TreeView treeView, XmlNode node)
{
if (treeView.HasItems)
{
//cast to xml-nodes
var xmlNodeList = treeView.Items.Cast<XmlNode>(); ;
//node at root level? -> select it
if (xmlNodeList.Contains(node))
{
(treeView.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem).IsSelected = true;
}
else
{
//get rootnode
XmlNode rootNode = GetRootNode(node, xmlNodeList);
//get a list of parent nodes
List<XmlNode> parentNodes = new List<XmlNode>();
GetAllParentNodes(rootNode, node, ref parentNodes);
parentNodes.Reverse();
//finaly, select the node
SelectNode(parentNodes, node, ref treeView, null);
}
}
}
/// <summary>
/// Goes recursiv down the parent nodes until he finds a node that is in the xmlNodeList.
/// Returns null if he can´t find anything.
/// </summary>
/// <param name="node">The start node.</param>
/// <param name="xmlNodeList">A list with possible rootnodes.</param>
/// <returns>The rootnode</returns>
private static XmlNode GetRootNode(XmlNode node, IEnumerable<XmlNode> xmlNodeList)
{
if (!xmlNodeList.Contains(node) && node.ParentNode != null)
{
return GetRootNode(node.ParentNode, xmlNodeList);
}
else if (xmlNodeList.Contains(node)) return node;
else return null;
}
/// <summary>
/// Returns all parent nodes from the actual node within the rootNode. Works recursiv.
/// </summary>
/// <param name="rootNode">The rootnode.</param>
/// <param name="actualNode">The startnode</param>
/// <param name="parentNodes">The rererenz to the outputlist</param>
private static void GetAllParentNodes(XmlNode rootNode, XmlNode actualNode, ref List<XmlNode> parentNodes)
{
if (actualNode.ParentNode != null && !actualNode.Equals(rootNode))
{
parentNodes.Add(actualNode.ParentNode);
GetAllParentNodes(rootNode, actualNode.ParentNode, ref parentNodes);
}
}
/// <summary>
/// Select a XmlNode from a TreeView that is databound to a xmlDataProvider.
/// </summary>
/// <param name="parentNodes">All the parent nodes, first in the list is the rootnode.</param>
/// <param name="node">The node to select.</param>
/// <param name="treeView">A referenz to the TreeView.</param>
/// <param name="item">Variable for the recursion.</param>
private static void SelectNode(List<XmlNode> parentNodes, XmlNode node, ref TreeView treeView, [Optional, DefaultParameterValue(null)] TreeViewItem item)
{
if (parentNodes.Count > 0)
{
TreeViewItem tvItem;
if (item != null)
tvItem = item.ItemContainerGenerator.ContainerFromItem(parentNodes.First()) as TreeViewItem;
else
tvItem = treeView.ItemContainerGenerator.ContainerFromItem(parentNodes.First()) as TreeViewItem;
parentNodes.RemoveAt(0);
SelectNode(parentNodes, node, ref treeView, tvItem);
}
else if (item != null)
{
(item.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem).IsSelected = true;
}
}