【问题标题】:Display hierarchy tree using WinForms DevExpress XtraGrid c#使用 WinForms DevExpress XtraGrid c# 显示层次结构树
【发布时间】:2014-07-08 08:38:48
【问题描述】:

我有分层数据结构,由以下对象组成:

Class A
{
*some properties
*list<A> SubNodes
}

现在我需要在某种可视化树中显示这个层次结构。 我正在使用 WinForms C#/ 你能告诉我如何显示这样的树吗? Standart TreeView 没有 DataSource 属性,DevExpress XtraTreeView 使用具有 Id/ParentID 关系的 DataSource 普通源。我使用过 XtraGrid,但无法正确配置详细信息视图。你能告诉我我可以通过什么方式来处理这个问题吗?

更新

在白天的讨论中,我们决定 TreeList 不适合我们。因为我们需要提供 XtraGrid 的自动筛选行和组面板(我可以在其中拖动列进行分组)的所有东西。 因此,如果没有使用 XtraGrid 实现这种树的解决方案,我应该关闭这个问题。

【问题讨论】:

  • 我的班级有很多属性,如 Amount、StartDate、Owner,我需要显示这些字段,如带有列的 gridrow。但是树视图只能显示一个属性。

标签: c# winforms tree devexpress


【解决方案1】:

您可以使用TreeList.IVirtualTreeListData接口。
这是一个例子:

public class A
{
    public A(string property0, string property1, string property2)
    {
        Property0 = property0;
        Property1 = property1;
        Property2 = property2;

        SubNodes = new List<A>();
    }

    public string Property0 { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    public List<A> SubNodes { get; private set; }
}

public class TreeDataSource : List<A>, TreeList.IVirtualTreeListData
{
    void TreeList.IVirtualTreeListData.VirtualTreeGetChildNodes(VirtualTreeGetChildNodesInfo info)
    {
        var a = info.Node as A;

        info.Children = a.SubNodes;
    }

    void TreeList.IVirtualTreeListData.VirtualTreeGetCellValue(VirtualTreeGetCellValueInfo info)
    {
        var a = info.Node as A;

        switch (info.Column.FieldName)
        {
            case "Property0":
                info.CellData = a.Property0;
                break;
            case "Property1":
                info.CellData = a.Property1;
                break;
            case "Property2":
                info.CellData = a.Property2;
                break;
        }
    }

    void TreeList.IVirtualTreeListData.VirtualTreeSetCellValue(VirtualTreeSetCellValueInfo info)
    {
        var a = info.Node as A;

        switch (info.Column.FieldName)
        {
            case "Property0":
                a.Property0 = (string)info.NewCellData;
                break;
            case "Property1":
                a.Property1 = (string)info.NewCellData;
                break;
            case "Property2":
                a.Property2 = (string)info.NewCellData;
                break;
        }
    }
}

例子的用法:

var treeDataSource = new TreeDataSource();
//Add top level nodes
treeDataSource.Add(new A("Node 0, Property 0", "Node 0, Property 1", "Node 0, Property 2"));
treeDataSource.Add(new A("Node 1, Property 0", "Node 1, Property 1", "Node 1, Property 2"));
treeDataSource.Add(new A("Node 2, Property 0", "Node 2, Property 1", "Node 2, Property 2"));
//Add subnodes for first node.
treeDataSource[0].SubNodes.Add(new A("Node 0.0, Property 0", "Node 0.0, Property 1", "Node 0.0, Property 2"));
treeDataSource[0].SubNodes.Add(new A("Node 0.1, Property 0", "Node 0.1, Property 1", "Node 0.1, Property 2"));
treeDataSource[0].SubNodes.Add(new A("Node 0.2, Property 0", "Node 0.2, Property 1", "Node 0.2, Property 2"));
//Add subnodes for second node.
treeDataSource[1].SubNodes.Add(new A("Node 1.0, Property 0", "Node 1.0, Property 1", "Node 1.0, Property 2"));
treeDataSource[1].SubNodes.Add(new A("Node 1.1, Property 0", "Node 1.1, Property 1", "Node 1.1, Property 2"));
treeDataSource[1].SubNodes.Add(new A("Node 1.2, Property 0", "Node 1.2, Property 1", "Node 1.2, Property 2"));

var treeList = new TreeList();

treeList.Columns.AddField("Property0").Visible = true;
treeList.Columns.AddField("Property1").Visible = true;
treeList.Columns.AddField("Property2").Visible = true;

treeList.DataSource = treeDataSource;

Controls.Add(treeList);
treeList.Dock = DockStyle.Fill;            

示例结果:

【讨论】:

  • 我已经尝试过您的解决方案,并在树列表列中创建了源 Property0、Property1、Property2。但是树列表只显示顶层,当我展开第一行时,那里是空白行。
  • @Kostya 我已经用示例更新了我的答案。
  • 不,只是复制了您的代码,而我的 TreeList 只显示顶级行。当我在那里展开三个没有值的空白行时。
  • 我刚刚复制了整个代码,没有做任何修改。粘贴到按钮单击事件的用法示例。只是带有按钮的空白表单。
  • @flexo 我把它重命名为TreeDataSource
【解决方案2】:

有两种推荐的方法将封装树结构的业务对象绑定到 DevExpress TreeList:

1) 调整对象以在 TreeList 控件中显示。在这种情况下,对象必须实现DevExpress.XtraTreeList.IVirtualTreeListData 接口。请参阅this article,了解更多信息。
示例:How to: Implement a Tree Structure for a Business Object

2) 处理特定 TreeList 的事件并为根节点和子节点提供数据。 请参阅this article,了解更多信息。
示例:How to: Load Data Dynamically via Events

【讨论】:

    【解决方案3】:

    如果您想使用 XtraGrid 进行层次结构,则可以使用IRelationList 接口。
    这是一个例子:

    public class A
    {
        public A(string property0, string property1, string property2)
        {
            Property0 = property0;
            Property1 = property1;
            Property2 = property2;
    
            SubNodes = new List<A>();
        }
    
        public string Property0 { get; set; }
        public string Property1 { get; set; }
        public string Property2 { get; set; }
    
        public List<A> SubNodes { get; private set; }
    }
    
    public class DataSource : List<A>, IRelationList
    {
        IList IRelationList.GetDetailList(int index, int relationIndex)
        {
            return this[index].SubNodes;
        }
    
        string IRelationList.GetRelationName(int index, int relationIndex)
        {
            return null;
        }
    
        bool IRelationList.IsMasterRowEmpty(int index, int relationIndex)
        {
            return this[index].SubNodes.Count == 0;
        }
    
        int IRelationList.RelationCount
        {
            get { return 1; }
        }
    }
    

    例子的用法:

    var dataSource = new DataSource();
    //Add top level nodes
    dataSource.Add(new A("Node 0, Property 0", "Node 0, Property 1", "Node 0, Property 2"));
    dataSource.Add(new A("Node 1, Property 0", "Node 1, Property 1", "Node 1, Property 2"));
    dataSource.Add(new A("Node 2, Property 0", "Node 2, Property 1", "Node 2, Property 2"));
    //Add subnodes for first node.
    dataSource[0].SubNodes.Add(new A("Node 0.0, Property 0", "Node 0.0, Property 1", "Node 0.0, Property 2"));
    dataSource[0].SubNodes.Add(new A("Node 0.1, Property 0", "Node 0.1, Property 1", "Node 0.1, Property 2"));
    dataSource[0].SubNodes.Add(new A("Node 0.2, Property 0", "Node 0.2, Property 1", "Node 0.2, Property 2"));
    //Add subnodes for second node.
    dataSource[1].SubNodes.Add(new A("Node 1.0, Property 0", "Node 1.0, Property 1", "Node 1.0, Property 2"));
    dataSource[1].SubNodes.Add(new A("Node 1.1, Property 0", "Node 1.1, Property 1", "Node 1.1, Property 2"));
    dataSource[1].SubNodes.Add(new A("Node 1.2, Property 0", "Node 1.2, Property 1", "Node 1.2, Property 2"));
    //Add subnodes for second node in fisrt subnode.
    dataSource[0].SubNodes[1].SubNodes.Add(new A("Node 0.1.0, Property 0", "Node 0.1.0, Property 1", "Node 0.1.0, Property 2"));
    dataSource[0].SubNodes[1].SubNodes.Add(new A("Node 0.1.1, Property 0", "Node 0.1.1, Property 1", "Node 0.1.1, Property 2"));
    dataSource[0].SubNodes[1].SubNodes.Add(new A("Node 0.1.2, Property 0", "Node 0.1.2, Property 1", "Node 0.1.2, Property 2"));
    
    var gridControl = new GridControl();
    
    var view = new GridView(gridControl);           
    
    gridControl.MainView = view;
    gridControl.DataSource = dataSource;
    gridControl.Dock = DockStyle.Fill;
    
    view.OptionsDetail.ShowDetailTabs = false;
    
    Controls.Add(gridControl);
    

    示例结果:

    另外,您可以查看«How to emulate a TreeList using the master-detail GridView» 示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多