【问题标题】:Populating TreeView From Object从对象填充 TreeView
【发布时间】:2016-11-16 13:12:21
【问题描述】:

我有一个相当简单的类结构,其中有 Graphic 对象,每个都包含一个 List<Symbol> 并且每个 Symbol 都包含一个 List<Alias>:amgonst 它们的其他属性。

显而易见的方法(和我当前的方法)是使用嵌套的foreach 循环来生成节点并填充树视图(这实际上工作正常),如下所示:

    public void ToTree(TreeView treeControl)
    {
        treeControl.Nodes.Clear();
        List<TreeNode> graphicsNodes = new List<TreeNode>();
        foreach (Graphic graphic in Graphics)
        {
            List<TreeNode> symbolNodes = new List<TreeNode>();
            foreach (Symbol symbol in graphic.Symbols)
            {
                List<TreeNode> aliasNodes = new List<TreeNode>();
                foreach (Alias alias in symbol.Aliases)
                {
                    aliasNodes.Add(new TreeNode(alias.AliasName + ": " + alias.AliasValue));
                }
                symbolNodes.Add(new TreeNode(symbol.SymbolName, aliasNodes.ToArray()));
            }
            graphicsNodes.Add(new TreeNode(graphic.FileName, symbolNodes.ToArray()));
        }
        treeControl.Nodes.AddRange(graphicsNodes.ToArray());
    }

但是,我很好奇是否可以在我的类中实现任何东西,或者我可以重载任何方法,以便我可以简单地执行类似于treeView.Nodes.Add(graphic) 的操作。

理想情况下,这将允许我确定使用NodeClickEvent 单击哪个对象,而不必获取节点的文本然后单独执行搜索。

这样我就可以从该节点内直接访问每个对象的字段和成员,从而更容易从TreeView 点击事件中修改属性。

【问题讨论】:

  • 如果您创建一个 TreeNodeCollection 对象,这将是可能的。但不太可能是根本性的改进。您应该使用 Begin/EndUpdate() 来避免过度绘制。
  • 您介意详细说明这个 Beging/EndUpdate() 点吗?
  • @HansPassant 奇怪的是,TreeNodeCollection 没有公共构造函数,虽然它不是密封的(System.Web 中的那个是密封的),但这使得它几乎不可能尽可能地扩展它' t 子类化它或实例化它。除非你有绝招......

标签: c# winforms treeview


【解决方案1】:

您可以做的是创建TreeNode 的子类,在它们的构造函数中接受您的类。然后,您可以让每个子类实现该类型的特定处理。我查看了suggestion from Hans 以对TreeNodeCollection 做一些有用的事情,但是这个类没有公共构造函数,所以我不知道它应该如何工作。

我从您的示例中提取的三个类的简单实现如下所示:

图形和图形节点

public class GraphicNode:TreeNode
{ 
    // takes a Graphic instance
    public GraphicNode(Graphic grp)
    {
        // how do you want to represent it
        this.Text = grp.FileName;
        // and this class 'knows' how to handle its children
        Nodes.AddRange(grp.Symbols.Select(s => new SymbolNode(s)).ToArray());
    }
}

符号和符号节点

public class SymbolNode:TreeNode
{
    public SymbolNode(Symbol sym)
    {
        this.Text = sym.SymbolName;
        Nodes.AddRange(sym.Aliases.Select(ali => new AliasesNode(ali)).ToArray());
    }
}

别名和别名节点

注意这个类是如何实现公共Click 方法的。您可以从 NodeMouseClick 事件中利用它。

public class AliasesNode:TreeNode
{
    public AliasesNode(Aliases al)
    {
        this.Text = String.Format("{0} - {1}", al.AliasName, al.AliasValue);   
    }

    public void Click()
    {
        MessageBox.Show(new String(this.Text.Reverse().ToArray()));
    }                
}

填充树视图

以下代码通过添加 GraphicNode 来填充 Treeview。通过首先调用 BeginUpdate,我们可以防止控件在添加的每个节点上绘制其内容。不要忘记调用EndUpdate,以便控件布局和重绘所有新添加的节点。注意这里只需要添加GraphicNodes,其他节点的添加由子类TreeNodes处理。

// tell the control to hold its paint/redraw events until 
// we're done adding all items
tv.BeginUpdate();
foreach(var g in graphics)
{
    tv.Nodes.Add(new GraphicNode(g));
}
// done, draw all nodes now
tv.EndUpdate();

如果将 NodeMouseClick 连接到以下事件处理程序,则可以访问 TreeNode 的具体实现:

private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    var node = e.Node as AliasesNode;
    if (node != null)
    {
        node.Click();
    }
}

当我们单击 AliasTreenode 时,我们应该会看到在该类的 Click 方法中实现的 MessageBox 弹出窗口:

【讨论】:

  • 这太棒了,谢谢。顺便说一句,你是如何制作那个动画的?
猜你喜欢
  • 1970-01-01
  • 2012-12-09
  • 2017-05-25
  • 2017-06-05
  • 2010-10-22
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
相关资源
最近更新 更多