2012-04-26 4 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 s в своем коде и настройте свойства через сеттеры. Измените класс 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" и пространство имен "Бар":

<%@ 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> 

CodeBehind:

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

+0

@ Это отличная статья. В то же время я прочитал это, я читал эту ссылку: http://support.microsoft.com/kb/2527108. Я внедрил ваше решение, но получил эту ошибку: «Ошибка 6 Тип или имя пространства имен« CustomTreeView »не существует в пространстве имен« System.Web.UI.WebControls ». Мне нужно добавить что-то в код aspx? – Ninita

+1

@Ninita Это на самом деле ошибка в примере. Префикс тега должен быть тем, который вы регистрируете в соответствии с Директивой по страницам. Если ваш элемент управления определен в сборке под названием 'Foo' в пространстве имен' Bar', вы должны установить 'Assembly =" Foo "и' Namespace = "Bar" 'в директиве' Register'.Я обновил пример – Tung

0

Вы можете перегрузить CreateNode в CustomTreeView классе:

protected CustomTreeNode CreateNode(int nodeId, string nodeType) 
{ 
    TreeNode res = base.CreateNode(); 
    res.NodeId = nodeId; 
    res.NodeType = nodeType; 
    return res; 
} 
+0

Перенесьте меня, я просто вижу, что мое решение не работает, потому что TreeNode не имеет членов NodeId и NodeType. – jahu

+0

Почему бы вам не удалить свой ответ, если вы считаете, что это неправильно? – Breeze