2012-04-26 125 views
4

我需要扩展TreeNode类,以便可以将自定义属性添加到每个节点(请参阅WebForms TreeNode不包含Tag属性)。所以这是我CustomTreeNode:创建自定义TreeView/TreeNode

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值已丢失,因为空构造函数返回没有任何值的节点。

任何帮助非常感谢。

回答

5

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

树节点类:

[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文件(假设您的自定义控制在装配 “富” 与命名空间 “酒吧” 中定义:

<%@ 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; 
    } 
+0

谢谢。这是非常有用和有用的知道。它工作完美。 – pedroAx 2012-04-26 09:35:49

+0

@Tung这是一篇很棒的文章。同时我阅读了这篇文章,我正在阅读这个链接:http://support.microsoft.com/kb/2527108。我实现了你的解决方案,但是我得到了这个错误:'错误6名称空间'System.Web.UI.WebControls'中不存在类型或命名空间名'CustomTreeView'。我需要在aspx代码中添加一些东西? – Ninita 2014-07-31 09:19:57

+1

@Ninita这实际上是一个例子中的错误。标签前缀应该是通过页面指令注册的。如果你的控件是在名为'Bar'的名为'Foo'的程序集中定义的,那么你可以在'Register'指令中设置'Assembly =“Foo”'和'Namespace =“Bar”'。我更新了这个例子 – Tung 2014-08-01 00:01:35

0

你可以在CustomTreeView类重载CreateNode

​​
+0

原谅我,我只是看到我的解决方案无法正常工作,因为TreeNode没有成员NodeId和NodeType。 – jahu 2012-04-26 08:25:42

+0

如果你认为这是错的,你为什么不删除你的答案? – Breeze 2016-03-29 06:28:57