处理可编辑的分层数据/TreeView~DataGrid 混合 [英] Handle editable hierarchical data / TreeView~DataGrid hybrid

查看:17
本文介绍了处理可编辑的分层数据/TreeView~DataGrid 混合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找混合了 TreeView 和 DataGrid 的 WPF 控件,例如 Visual Studio 调试器或 QuickBooks 联系人列表等.

I am looking for a WPF control which is a hybrid of TreeView and DataGrid, something like the Visual Studio debugger or QuickBooks contacts list etc.

关于如何在 WPF 中处理可编辑分层数据的任何其他解决方案也将非常受欢迎.

Any other solution on how to handle editable hierarchical data in WPF will be very welcommed as well.

推荐答案

在我看来,如果您正确设计视图模型,这似乎是一件相当简单的事情.

This seems to me like a reasonably straightforward thing to implement if you design your view model properly.

您基本上以与在普通数据网格中显示它们相同的方式设计项目,即每个项目的每一列都有一个属性.很可能,您的底层数据模型是分层的,但网格绑定到的集合将被扁平化,即,将包含一个项目,用于层次结构中的每个节点,而不管父/子关系如何.

You basically design the items the same way you would if displaying them in a normal data grid, i.e. each item has a property for each column. In all likelihood, your underlying data model is hierarchical, but the collection that the grid is bound to is going to be flattened, i.e. will contain an item for each node in the hierarchy irrespective of parent/child relationships.

项目视图模型有一些额外的属性:LevelChildrenIsExpandedIsVisible.Level 是节点祖先的计数,Children 包含子视图模型节点,IsExpanded 用于 UI,IsVisible 如果节点可见,则为真.它还实现了一个名为 VisibleDescendants 的属性:

The item view model has some additional properties: Level, Children, IsExpanded, and IsVisible. Level is a count of the node's ancestors, Children contains the child view model nodes, IsExpanded is used in the UI, and IsVisible is true if the node is visible. It also implements a property called VisibleDescendants:

public IEnumerable<NodeViewModel> VisibleDescendants
{
   get
   {
      return Children
             .Where(x => x.IsVisible)
             .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants)));
   }
}

您在控件第一列项目的样式中使用 LevelHasChildrenIsExpanded:它们控制左边距和显示什么样的图标(如果有).

You use Level, HasChildren, and IsExpanded in the style for the item in the control's first column: they control the left margin and what kind of icon (if any) is displayed.

您还需要实现 ExpandCommandCollapseCommand 属性.如果 Children.Any() 为真且 IsExpanded 为假,则启用 ExpandCommand,并且启用 CollapseCommand如果 Children.Any() 为真且 IsExpanded 为真.这些命令在执行时会更改 IsExpanded 的值.

You also need to implement ExpandCommand and CollapseCommand properties. The ExpandCommand is enabled if Children.Any() is true and IsExpanded is false, and the CollapseCommand is enabled if Children.Any() is true and IsExpanded is true. These commands, when executed, change the value of IsExpanded.

这就是有趣的地方.实现这一点的简单方法可能对您有用:项目由父视图模型公开,其 Items 属性不是集合.相反,它是一个沿着子视图模型链向下传播的枚举器,并且只产生可见节点:

And here's where it gets interesting. The simple way to implement this may work for you: the items are exposed by a parent view model whose Items property is not a collection. Instead, it's an enumerator that travels down the chain of child view models and yields only the visible nodes:

public IEnumerable<NodeViewModel> Items
{
   get
   {
      return _Items
             .Where(x => x.IsVisible)
             .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants));
   }
}

每当任何后代的 IsVisible 属性更改时,父视图模型都会为 Items 属性引发 PropertyChanged,这会强制重新填充数据网格.

Whenever any descendant's IsVisible property changes, the parent view model raises PropertyChanged for the Items property, which forces the data grid to repopulate.

还有一个不太简单的实现,您可以将 Items 属性设为一个实现 INotifyCollectionChanged 的类,并引发适当的 CollectionChanged 事件当后代节点变得可见/不可见,但您只想在性能有问题时去那里.

There's a less simple implementation too, where you make the Items property a class that implements INotifyCollectionChanged, and that raises the proper CollectionChanged events when descendant nodes become visible/invisible, but you only want to go there if performance is an issue.

这篇关于处理可编辑的分层数据/TreeView~DataGrid 混合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆