【问题标题】:How to inherit from the treenode class?如何从treenode类继承?
【发布时间】:2009-09-17 11:13:32
【问题描述】:

我有一个继承自 TreeNode 的类,称为 ExtendedTreeNode。将这种类型的对象添加到树视图中不是问题。但是如何从树视图中检索对象?

我试过这个:

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

return ((ExtendedTreeNode)node).Property;

但这不起作用。我收到此错误:无法将“System.Web.UI.WebControls.TreeNode”类型的对象转换为“PCK_Web_new.Classes.ExtendedTreeNode”。

我必须做些什么才能完成这项工作?

------------ 解决方案 -----

[编辑] 我的自定义 TreeNode 类如下所示:

public class ExtendedTreeNode : TreeNode
{
    private int _UniqueId;

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

这样我将节点添加到我的树视图中:

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);

这样我检索了我的 ExtendedTreeNode 对象:

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

我正在使用 .NET 3.5 SP1

【问题讨论】:

  • 你添加的Node都是ExtendedTreeNode吗?还是您也添加常规 TreeNode 对象?也许您可以展示如何将它们添加到 TreeView。
  • 是的,所有节点都必须是 ExtendedTreeNode 类型
  • 不知何故(至少在 ASP.NET 中)TreeView 将继承的TreeNodes 转换为TreeNodes。我试过覆盖Clone,但这没有帮助。我扩展的TreeNodes 仍然以某种方式变回了普通的。我想我需要使用反射器或其他东西来看看发生了什么。

标签: c# asp.net treeview treenode


【解决方案1】:

我找到了一个 Microsoft 示例,说明如何使用标签 here 实现 ASP.NET TreeView

除了子类化TreeNode 和添加Tag 属性之外,一些必要的重要步骤是:

您必须继承 TreeView 并覆盖 CreateNode 方法:

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

这可以防止TreeViewTreeNodes 覆盖您的新节点,而不是用您的扩展节点类型。

你需要有那个特定的构造函数可用。 (它似乎也可以使用默认构造函数,但很有可能他们使用这个是有充分理由的。)

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) {
   }

为了使用扩展的TreeView,您需要在标记中使用如下Register 行来导入类型:

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

...

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

您还必须在继承的 TreeNode 类中覆盖 LoadViewStateSaveViewState

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

这允许TreeView 在回发之间保留Tag 属性的值。

【讨论】:

  • 为什么不简单地公开对象标签 { get ;放; } ?
  • @dlchambers 当然,我可能只是在复制 MS 的实现。您实际上可以以任何您想要的方式扩展TreeNode;添加Tag 只是一种可能性。
【解决方案2】:

您可以尝试以下方法来获取父节点下的所有节点:

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

【讨论】:

  • 当我做 ExtendedTreeNode enode = node as ExtendedTreeNode; enode 始终为空。怎么会?
  • 在使用as强制转换(称为安全强制转换)时,如果强制转换失败,则将对象设置为null
  • 好的,我只是看看你是如何添加它们的。你会想要将我的示例从“node as ExtendedTreeNode”更改为“node.Tag as ExtendedTreeNode”。这让我想到了我的问题,你为什么要这样做?我认为您想创建 NT2 并使用它(即,不要创建“TreeNode tn = new TreeNode();”)。然后添加 TN2,而不是 tn,我的原始帖子应该可以工作。
  • 您的 ExtendedTreeNode 类应以以下内容开头:“public class ExtendedTreeNode : TreeNode”
【解决方案3】:

我假设您将节点创建为 ExtendedTreeNodes。

我注意到 XxxView(ListView、TreeView、DataGridView)控件往往会意外地克隆事物。你实现ICloneable.Clone ()了吗?

这可能行得通; TreeNode 虚拟实现了Clone ()

我发现它更容易,但使用树节点的 Tag 属性来实现扩展属性:

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

我强烈建议不要使用Clone ();这是一个脆弱的模式。使用 Tag 属性:

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

【讨论】:

  • 不,我没有实现 ICloneble.Clone() 我应该这样做吗?如果有,怎么做?
  • TreeNode的Tag属性不存在?
  • object TreeNode.Tag 确实存在于 Windows 窗体中。不确定 ASP.NET,但为什么不呢?
  • 假设你有一个合理的拷贝构造函数: public override object Clone() { return new ExtendedTreeNode (this);但是,Clone() 是一个非常脆弱的模式。我强烈建议您更加努力地寻找 .Tag () 属性。
  • 显示您的代码...您使用的是哪个版本的 .NET?我在 3.5 SP1;我没有 2.0 的文档。
猜你喜欢
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多