0

我有一个派生自TreeNode的TreeNode类,一个派生自TreeView的TreeView类,以及一个自定义树节点集合。当我尝试通过代码添加节点时,节点会正确添加和显示,但是当我尝试通过设计器集合编辑器添加节点时,设计器会生成代码,但不会立即显示更改。我必须构建项目才能显示它们,但节点计数器正在重置。我显然希望它在我单击集合编辑器中的“确定”按钮时立即显示更改。

此外,当它遇到BtnOK_click事件时,它会执行base.Items = array;base.EditValuevalue 设置为的行,array然后触发OnEditValueChanged()。但是,BtnOK_click如果值发生base.EditValue变化,并且当它命中 时,由于某种原因OnEditValueChanged(),值是 null。base.EditValue当我尝试执行类似的行时base.EditValue = array;,它会引发异常:Object reference not set to an instance of an object

以下是相关的集合编辑器方法:

//This is the event which triggers when the user presses the OK button in the collection editor
private void BtnOK_click(object sender, EventArgs e) {
    object[] array = new object[this.treeView1.Nodes.Count];
    for (int i = 0; i < array.Length; i++)
        array[i] = this.treeView1.Nodes[i].Clone();
    base.Items = array;
    this.treeView1.Dispose();
    this.treeView1 = null;
}


protected override void OnEditValueChanged() {
    if (base.EditValue != null) {
        object[] items = base.Items;
        this.propertyGrid1.Site = new PropertyGridSite(base.Context, this.propertyGrid1);
        MyTreeNode[] array = new MyTreeNode[items.Length];
        for (int i = 0; i < items.Length; i++)
            array[i] = (MyTreeNode)((MyTreeNode)items[i]).Clone();
        this.treeView1.Nodes.Clear();
        this.treeView1.Nodes.AddRange(array);
        this.curNode = null;
        this.btnAddChild.Enabled = false;
        this.btnDelete.Enabled = false;
        MyTreeView treeView = this.TreeView;
        if (treeView != null)
            this.SetImageProps(treeView);
        if (items.Length > 0 && array[0] != null)
            this.treeView1.SelectedNode = array[0];
    }
}

这是TreeNodeClone Method 及其相关方法和类(我不知道这是否会导致问题,因为该方法似乎工作正常):

private const string si_children = "children";
private const string si_propBag = "PropBag";

public override object Clone() {
    MyTreeNode node;
    SerializationInfo si;
    SerializationInfo siDemo = new SerializationInfo(typeof(MyTreeNode), new MyTreeNodeFormatterConverter());
    StreamingContext sc = new StreamingContext();
    bool hasPropBag = false;
    this.Serialize(siDemo, sc);
    try {
        siDemo.GetValue(si_propBag, typeof(OwnerDrawPropertyBag));
        hasPropBag = true;
    }
    catch {
    }
    if (this._nodes.Count > 0 || hasPropBag) {
        si = new SerializationInfo(typeof(MyTreeNode), new MyTreeNodeFormatterConverter());
        foreach (SerializationEntry se in siDemo) {
            if (se.Name.StartsWith(si_children))
                si.AddValue(se.Name, ((MyTreeNode)se.Value).Clone(), typeof(MyTreeNode));
            else if (se.Name == si_propBag)
                si.AddValue(se.Name, OwnerDrawPropertyBag.Copy((OwnerDrawPropertyBag)se.Value), typeof(OwnerDrawPropertyBag));
            else
                si.AddValue(se.Name, se.Value, se.ObjectType);
        }
        node = new MyTreeNode(si, sc);
    }
    else
        node = new MyTreeNode(siDemo, sc);
    return node;
}

private class MyTreeNodeFormatterConverter : FormatterConverter {
    public MyTreeNodeFormatterConverter()
        : base() {
    }

    public new object Convert(object value, Type type) {
        Type value_type;
        if (value == null)
            throw new ArgumentNullException("value");
        value_type = value.GetType();
        //Since I'm only adding nodes of type MyTreeNode, TreeNode nodes can be safely cast back to their original type MyTreeNode
        if (value_type == typeof(MyTreeNode) || value_type == typeof(TreeNode))
            return value as MyTreeNode;
        else if (value_type == typeof(OwnerDrawPropertyBag))
            return value as OwnerDrawPropertyBag;
        else
            return base.Convert(value, type);
    }
}

protected MyTreeNode(SerializationInfo si, StreamingContext sc)
    : base(si, sc) {
}

protected override void Deserialize(SerializationInfo si, StreamingContext sc) {
    MyTreeNode[] children;
    int base_nodes_count;
    base.Deserialize(si, sc);
    base_nodes_count = base.Nodes.Count;
    this.Init();
    if (base_nodes_count > 0) {
        children = new MyTreeNode[base_nodes_count];
        for (int i = 0; i < base_nodes_count; i++)
            children[i] = (MyTreeNode)si.GetValue(si_children + i, typeof(MyTreeNode));
        this._nodes.AddRangeBase(children);
    }
}

private void Init() {
    this._nodes = new MyTreeNodeCollection(this, base.Nodes);
}
4

1 回答 1

0

我通过向 TreeViewDesginer 添加以下行来显示添加的节点:

MyTreeNodeCollectionEditor.MyTreeNodeCollectionEditor uITypeEditor = this._targetProperty.GetEditor(typeof(UITypeEditor)) as MyTreeNodeCollectionEditor.MyTreeNodeCollectionEditor;
MyTree.MyTreeView treeView = (MyTree.MyTreeView)this._designer.Component;
treeView.Nodes.Clear();
treeView.Nodes.AddRange(uITypeEditor.nodes);
于 2014-08-12T19:30:00.877 回答