创建自定义树视图/树节点

本文关键字:树节点 视图 自定义 创建 | 更新日期: 2023-09-27 18:32:28

我需要扩展 TreeNode 类,以便我可以为每个节点添加自定义属性(参见 WebForms TreeNode 不包含 Tag 属性)。所以这是我的自定义树节点:

public class CustomTreeNode : TreeNode
{
    public CustomTreeNode()
    {               
    }
    public CustomTreeNode(int nodeId, string nodeType)
    {
        NodeId = nodeId;
        NodeType = nodeType;
    }
    public string NodeType { get; set; }
    public int NodeId { get; set; }
}

如果我创建一个自定义树节点并将其添加到树视图:

CustomTreeNode node = new CustomTreeNode(1, "CustomType");            
treeView.Nodes.Add(node);

然后,我将执行以下操作得到一个强制转换异常:

CustomTreeNode selectedNode = (CustomTreeNode)TreeView.SelectedNode;

因为 TreeView 返回的是 TreeNode,而不是 CustomTreeNode。

我已经做了一些阅读,看起来我需要扩展 TreeView 类,并覆盖 CreateNode() 方法以返回 CustomTreeNode 而不是 TreeNode。所以我创建了这个:

public class CustomTreeView : TreeView
{
    protected override TreeNode CreateNode()
    {
        return new CustomTreeNode();
    }
}

然而,问题是 CreateNode() 不接受任何参数,所以你必须为 CustomTreeNode 类调用空构造函数。因此,当我在上面创建自定义树节点时,当我从自定义树视图取回它时,nodeId 和 nodeType 值已经丢失,因为空构造函数返回一个没有任何值的节点。

任何帮助非常感谢。

创建自定义树视图/树节点

这就是我想出的(专家,欢迎任何建议)。 在代码隐藏中实例化CustomTreeNode,并通过资源库设置属性。修改 CustomTreeNode 类以将值保留在视图状态中。自定义树视图的CreateNode返回的节点将加载视图状态信息。

树节点类:

[DefaultProperty("Text")]
[ToolboxData("<{0}:CustomTreeNode runat=server></{0}:CustomTreeNode>")]
public class CustomTreeNode : TreeNode
{
    private const int NODE_TYPE = 1;
    private const int NODE_ID = 2;
    public string NodeType { get; set; }
    public int NodeId { get; set; }
    protected override void LoadViewState(Object savedState)
    {
        if (savedState != null)
        {
            object[] myState = (object[])savedState;
            if (myState[0] != null)
                base.LoadViewState(myState[0]);
            if (myState[NODE_TYPE] != null)
                this.NodeType = (string)myState[NODE_TYPE];
            if (myState[NODE_ID] != null)
                this.NodeId = (int)myState[NODE_ID];
        }
    }
    protected override Object SaveViewState()
    {
        object baseState = base.SaveViewState();
        object[] allStates = new object[3];
        allStates[0] = baseState;
        allStates[NODE_TYPE] = this.NodeType;
        allStates[NODE_ID] = this.NodeId;
        return allStates;
    }
}

树视图类:

[DefaultProperty("Text")]
[ToolboxData("<{0}:CustomTreeView runat=server></{0}:CustomTreeView>")]
public class CustomTreeView : TreeView
{
    protected override TreeNode CreateNode()
    {
        // Tree node will get its members populated with the data from VIEWSTATE
        return new CustomTreeNode();
    }
}

简单的.aspx文件(假设自定义控件是在程序集"Foo"和命名空间"Bar"中定义的:

<%@ Register TagPrefix="customControl" Assembly="Foo" Namespace="Bar"  %>
<customControl:CustomTreeView ID="sampleTree" 
    runat="server" onselectednodechanged="sampleTree_SelectedNodeChanged"></customControl:CustomTreeView>
<asp:Label ID="lblSelectedNode" runat="server" ></asp:Label>

代码隐藏:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            PopulateTree();
        }
    }
    private void PopulateTree()
    {
        sampleTree.Nodes.Clear();
        CustomTreeNode root = new CustomTreeNode();
        root.Value = "root node";
        sampleTree.Nodes.Add(root);
        // Creating some fake nodes (you would of course be using real data)
        for (int i = 0; i < 10; i++)
        {
            CustomTreeNode child = new CustomTreeNode();
            child.NodeId = i;               // Saved in ViewState
            child.NodeType = "Type " + i;   // Saved in ViewState
            child.Value = child.NodeType;
            root.ChildNodes.Add(child);
        }
    }
    protected void sampleTree_SelectedNodeChanged(object sender, EventArgs e)
    {
        CustomTreeView cTreeView = (CustomTreeView) sender;
        lblSelectedNode.Text = ((CustomTreeNode)cTreeView.SelectedNode).NodeType;
    }