How to inherit from the treenode class?

2019-07-10 04:47发布

问题:

I have a class that inherits from TreeNode, called ExtendedTreeNode. To add an object of this type to the treeview is not a problem. But how do I retrieve the object from the treeview?

I have tried this:

TreeNode node = tvManual.Find("path/to/node"); // tvManual is a treeview

return ((ExtendedTreeNode)node).Property;

But this doesn't work. I get this error: Unable to cast object of type 'System.Web.UI.WebControls.TreeNode' to type 'PCK_Web_new.Classes.ExtendedTreeNode'.

What do I have to do to make this work?

------------ SOLUTION -----------------

[Edit] My custom TreeNode class looks like this:

public class ExtendedTreeNode : TreeNode
{
    private int _UniqueId;

    public int UniqueId
    {
        set { _UniqueId = value; }
        get { return _UniqueId; }
    }
    public ExtendedTreeNode()
    {
    }
}

And this way I add Nodes to my treeview:

ExtendedTreeNode TN2 = new ExtendedTreeNode();

TN2.Text = "<span class='Node'>" + doc.Title + "</span>";
TN2.Value = doc.ID.ToString();
TN2.NavigateUrl = "ViewDocument.aspx?id=" + doc.ID + "&doc=general&p=" + parent;
TN2.ImageUrl = "Graphics/algDoc.png";
TN2.ToolTip = doc.Title;
TN2.UniqueId = counter;

tvManual.FindNode(parent).ChildNodes.Add(TN2);

And this way I retrieve my ExtendedTreeNode object:

TreeNode node = tvManual.Find("path/to/node");
ExtendedTreeNode extNode = node as ExtendedTreeNode;
return extNode.UniqueId;

I am using .NET 3.5 SP1

回答1:

You could try the following to get all nodes under your parent:

TreeNode[] parentNode = treeView1.Nodes.Find (parentid, true);
foreach(TreeNode node in parentNode)
{
    ExtendedTreeNode ext_tree_node = node as ExtendedTreeNode;
    if(ext_tree_node != null)
    {
        // Do your work
    }
}


回答2:

I found a Microsoft example for how to implement an ASP.NET TreeView with tags here.

Some important steps that are necessary besides just subclassing TreeNode and adding a Tag property are:

You must subclass TreeView and override the CreateNode method:

public sealed class TaggedTreeView : TreeView {
   protected override TreeNode CreateNode() {
      return new TaggedTreeNode(this, false);
   }
}

This prevents the TreeView from overwriting your new nodes with TreeNodes instead of with your extended type of node.

You will need to have that particular constructor available. (It seems to work using the default constructor, too, but there's a good chance there's a good reason why they used this one.)

public sealed class TaggedTreeNode : TreeNode {
   object _Tag;

   public object Tag { get { return _Tag; } set { _Tag = value; } }

   ...

   protected internal TaggedTreeNode(TreeView owner, bool isRoot)
   : base(owner, isRoot) {
   }

In order to use the extended TreeView you will need a Register line like the following in your markup to import the type:

<%@ Register TagPrefix="asp" Namespace="MyNamespace" Assembly="MyAssembly" %>

...

<asp:TaggedTreeView ID="taggedTreeView" runat="server" />

You must also override LoadViewState and SaveViewState in your inherited TreeNode class:

public sealed class TaggedTreeNode : TreeNode {

   ...

   protected override void LoadViewState(object state) {
      var arrState = (object[])state;
      _Tag = arrState[0];
      base.LoadViewState(arrState[1]);
   }

   protected override object SaveViewState() {
      var arrState = new object[2];
      arrState[1] = base.SaveViewState();
      arrState[0] = _Tag;
      return arrState;
   }

This allows the TreeView to preserve the value of your Tag properties between postbacks.



回答3:

I assume you're creating the nodes as ExtendedTreeNodes.

I've noticed that the XxxView (ListView, TreeView, DataGridView) controls tend to clone things unexpectedly. Have you implemented ICloneable.Clone ()?

That may work; TreeNode implements Clone () virtually.

I find it easier, though to implement extended properties using the Tag property of the treenode:

TreeNode node = tvManual.Find("path/to/node");
return node.Tag as ExtendedTreeNode;

I strongly recommend against using Clone (); it's a fragile pattern. Use the Tag property:

class ExtendedInfo
{
    string NavigateUrl;
    string ImageUrl;
    int UniqueId;

    // other custom properties go here
}

// ...

void CreateTreeNode ()
{
    TreeNode TN = new TreeNode();

    string parent = "parent";    

    TN.Text = "<span class='Node'>" + doc.Title + "</span>";
    TN.Value = doc.ID.ToString();
    TN.ToolTip = doc.Title;

    ExtendedInfo extInfo = new ExtendedInfo;
    extInfo.NavigateUrl = "ViewDocument.aspx?id=" + doc.ID + "&doc=general&p=" + parent;
    extInfo.ImageUrl = "Graphics/algDoc.png";
    extInfo.UniqueId = counter;

    TN.Tag = extInfo;
}

// ...

ExtendedInfo GetExtendedInfo (TreeNode node)
{
    return node.Tag as ExtendedInfo;
}