如何为WPF的TreeViewItem添加可访问的自定义属性?
为WPF TreeViewItem添加自定义属性的问题与解决方法
问题背景
需要给WPF的TreeViewItem添加类似Header的自定义属性TreeViewType供代码调用,先后尝试两种方案均遇到问题。
方案一:直接注册依赖属性(编译失败)
尝试直接给TreeViewItem注册依赖属性,代码如下:
public static readonly DependencyProperty TreeViewTypeProp = DependencyProperty.Register( "TreeViewType", typeof(string), typeof(TreeViewItem), new PropertyMetadata("Root") ); public string TreeViewType { get { return (string)GetValue(TreeViewTypeProp); } set { SetValue(TreeViewTypeProp, value); } }
问题:在调用代码中无法访问TreeViewType属性,编译报错。调用代码片段:
public bool AddNewTreeviewChild(ItemCollection selectedTreeView, TreeViewItem selectedItem) { if (selectedTreeView.Contains(selectedItem)) { var newChild = new TreeViewItemExtension(); newChild.Header = NewItem.Text; newChild.TreeViewType = DesignateChildType(); // 此处编译失败,无法识别TreeViewType selectedItem.Items.Add(newChild); } foreach (TreeViewItem item in selectedTreeView) { if (AddNewTreeviewChild(item.Items, selectedItem)) { return true; } } return false; }
原因:WPF中不能直接给现有控件类(如TreeViewItem)添加依赖属性,这种写法不符合类型扩展规范,编译器无法识别新增的属性。
方案二:继承TreeViewItem实现扩展类(属性丢失)
通过继承TreeViewItem创建扩展类,添加自定义属性:
public class TreeViewItemExtension : TreeViewItem { public string TreeViewType { get; set; } public TreeViewItemExtension () { } }
问题:新增项的TreeViewType属性丢失,强制转换也无法获取属性值。
原因:TreeView的Items集合在遍历时常被当作TreeViewItem类型处理,此时子类的自定义属性会被“切片”,必须显式转换为TreeViewItemExtension类型才能访问,但如果集合中存在原生TreeViewItem,转换会抛出异常。
最终解决方案:使用附加属性
采用附加属性方案实现自定义属性,调试时曾遇到GetTreeviewParent方法返回空值的问题,排查后发现是参数传递错误——误传了parent参数,改为传入目标item后问题解决。
附加属性实现代码
public static class TreeViewItemHelper { // 定义附加属性 public static readonly DependencyProperty TreeViewTypeProperty = DependencyProperty.RegisterAttached( "TreeViewType", typeof(string), typeof(TreeViewItemHelper), new PropertyMetadata("Root")); // 设置属性的静态方法 public static void SetTreeViewType(TreeViewItem element, string value) { element.SetValue(TreeViewTypeProperty, value); } // 获取属性的静态方法 public static string GetTreeViewType(TreeViewItem element) { return (string)element.GetValue(TreeViewTypeProperty); } // 修正后的父节点获取方法 public static TreeViewItem GetTreeviewParent(TreeViewItem item) { DependencyObject parent = VisualTreeHelper.GetParent(item); while (parent != null && !(parent is TreeViewItem)) { parent = VisualTreeHelper.GetParent(parent); } return parent as TreeViewItem; } }
调用示例
// 给TreeViewItem设置自定义属性 var newChild = new TreeViewItem(); newChild.Header = NewItem.Text; TreeViewItemHelper.SetTreeViewType(newChild, DesignateChildType()); selectedItem.Items.Add(newChild); // 获取TreeViewItem的自定义属性 foreach (TreeViewItem item in selectedTreeView) { string itemType = TreeViewItemHelper.GetTreeViewType(item); // 后续逻辑 }
内容的提问来源于stack exchange,提问作者Vlad SD
相关产品推荐
相关产品推荐

