如何在Treeview C#WPF中插入子项

我想在之前添加的TreeViewItem中添加子项。 像这样的代码的问题:

如何在WPF中的TreeView控件中插入子节点?

或者我尝试使用的许多其他变体,如:

for (int i = 1; i <= dataTreeview.Items.Count; i++) { TreeViewItem tempTVI = (TreeViewItem)dataTreeview.Items.GetItemAt(i); } 

是我得到一个InvalidCastExceptionexception,因为项目(在另一个stackoverflow问题中)或tempTVI是字符串而不是TreeViewItem

我不知道为什么会这样,我没有想法。

如果它有助于我在预览中使用Visual Studio 2015社区。

谢谢您的帮助。

WPF中的TreeView是ItemsControl的扩展。 基本上有两种方法可以使用这些控件,一种使动态更改树易于管理,另一种使完全静态的树很容易设置。

动态树木

TreeView设计方式是遵循MVVM设计模式。 这是一个简单的例子。

首先,在使用MVVM时,您始终需要某种实现属性更改通知的视图模型的基类。 这是最基本的例子:

 internal class ObservableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null) { var handler = PropertyChanged; if (handler != null) { handler.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } 

然后,您需要一个表示树中单个节点的数据的类。 例如:

 internal class Node : ObservableObject { private ObservableCollection mChildren; // Add all of the properties of a node here. In this example, // all we have is a name and whether we are expanded. public string Name { get { return _name; } set { if (_name != value) { _name = value; NotifyPropertyChanged(); } } } private string _name; public bool IsExpanded { get { return _isExpanded; } set { if (_isExpanded != value) { _isExpanded = value; NotifyPropertyChanged(); } } } private bool _isExpanded; // Children are required to use this in a TreeView public IList Children { get { return mChildren; } } // Parent is optional. Include if you need to climb the tree // from code. Not usually necessary. public Node Parent { get; private set; } public Node(Node parent = null) { mChildren = new ObservableCollection(); IsExpanded = true; Parent = parent; } } 

现在,为控件创建一个viewmodel,其中包含这些节点的集合。 在此示例中,viewmodel用于应用程序的主窗口:

 internal class MainWindowVM : ObservableObject { private ObservableCollection mRootNodes; public IEnumerable RootNodes { get { return mRootNodes; } } public MainWindowVM() { mRootNodes = new ObservableCollection(); // Test data for example purposes Node root = new Node() { Name = "Root" }; Node a = new Node(root) { Name = "Node A" }; root.Children.Add(a); Node b = new Node(root) { Name = "Node B" }; root.Children.Add(b); Node c = new Node(b) { Name = "Node C" }; b.Children.Add(c); Node d = new Node(b) { Name = "Node D" }; b.Children.Add(d); Node e = new Node(root) { Name = "Node E" }; root.Children.Add(e); mRootNodes.Add(root); } } 

最后,创建TreeView实例并将其设置为使用您的数据。 在此示例中, TreeView是主应用程序窗口中唯一的内容:

                  

完成此设置后,从现在开始,您只需操作viewmodel中的数据, TreeView将自动更新以反映这些更改。 这样,您永远不需要直接操纵控件。

以下是结果视图:

截图

静态树木

如果整个树都是提前知道的并且永远不会改变,那么您可以将其设置为非常简单:

           

这种方法的问题是,当您想以编程方式修改树时,它变得难以管理,因为您必须处理TreeView本身。 但是,它可以通过代码隐藏来实现。 例如,如果我想在名为“New Node”的“Node C”下添加一个新的子节点,我可以这样做:

 ((TreeViewItem)((TreeViewItem)((TreeViewItem)mTreeView.Items[0]).Items[1]).Items[0]).Items.Add(new TreeViewItem() { Header = "New Node" }); 

以这种方式工作会变得混乱。 由于我们在数据中没有树的并行表示,因此我们必须通过控件继续访问事物并进行转换。

一些其他设置

看看你的问题,看起来你没有遵循这些方法中的任何一种,而是有一个基本上像这样设置的TreeView:

  Node A Node B  

所以,你有一个充满字符串的TreeView 。 在内部, ItemsControl可以接受任何对象并将其包装在项容器中。 TreeView将在TreeViewItem实例中包装这些字符串。 但是,项仍然存储为字符串,访问TreeView.Items将返回您添加的字符串。

获取与TreeViewItem中的任意项相关联的TreeView实际上相当困难,因为您必须在根级别获取每个项目的容器,然后深入了解每个项目并获取其项目的容器,以此类推树直到找到你要找的物品。

您可以在此处找到有关如何查找项容器的示例。 请注意,您无法在TreeView中使用虚拟化以使其可靠地工作。 此外,我建议不要以这种方式工作,因为你自己也在努力。

您正在获取String因为这是TreeView必须绑定的源。

使用此方法可以迭代项目并检索它们所在的TreeViewItem容器:

  List GetChildren(TreeViewItem parent) { List children = new List(); if (parent != null) { foreach (var item in parent.Items) { TreeViewItem child = item as TreeViewItem; if (child == null) { child = parent.ItemContainerGenerator.ContainerFromItem(child) as TreeViewItem; } children.Add(child); } } return children; } 

请注意,它们在投射后检查TreeViewItem是否为null。 这是一种很好的做法,因为它可以防止空引用exception在发生错误时崩溃您的应用程序。

来源: https : //social.msdn.microsoft.com/Forums/vstudio/en-US/595f0c84-01e7-4534-b73b-704b41713fd5/traversing-the-children-of-a-treeviewitem

也许你忘记了标签? 如果您的xaml文件中包含以下内容:

   Hello World  

代码隐藏中的以下内容:

 var a = MyTreeView.Items.GetItemAt(0) as string; var b = MyTreeView.Items.GetItemAt(0) as TreeViewItem; var c = MyTreeView.Items.GetItemAt(1) as string; var d = MyTreeView.Items.GetItemAt(1) as TreeViewItem; 

变量a和d将为null,而b将是TreeViewItem,c将是一个字符串。