如何在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将是一个字符串。