【问题标题】:Creating custom TreeView/TreeNode创建自定义 TreeView/TreeNode
【发布时间】:2012-04-26 07:52:40
【问题描述】:

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

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 并将其添加到 TreeView:

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 类的空构造函数。所以当我在上面创建我的 CustomTreeNode 时,当我从 CustomTreeView 中取回它时,nodeId 和 nodeType 值已经丢失,因为空构造函数返回一个没有任何值的节点。

非常感谢任何帮助。

【问题讨论】:

    标签: c# asp.net webforms treeview treenode


    【解决方案1】:

    这是我想出的(专家,欢迎提出任何建议)。在后面的代码中实例化 CustomTreeNodes 并通过 setter 设置属性。修改您的 CustomTreeNode 类以将值保留在 ViewState 中。您的自定义树视图的CreateNode 返回的节点将加载 ViewState 信息。

    TreeNode 类:

    [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;
        }
    }
    

    TreeView 类:

    [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;
        }
    

    【讨论】:

    • 谢谢。知道这非常有帮助和有用。效果很好。
    • @Tung 这是一个很棒的帖子。在我阅读此内容的同时,我正在阅读此链接:support.microsoft.com/kb/2527108。我实施了您的解决方案,但出现此错误:Error 6 The type or namespace name 'CustomTreeView' does not exist in the namespace 'System.Web.UI.WebControls'。我需要在 aspx 代码中添加一些东西吗?
    • @Ninita 这实际上是示例中的一个错误。标签前缀应该是您通过页面指令注册的前缀。如果您的控件是在命名空间Bar 内名为Foo 的程序集中定义的,那么您将在Register 指令中设置Assembly="Foo"Namespace="Bar"。我已经更新了示例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多