2011-12-21 12 views
2

System.Windows.Forms.TreeViewを拡張し、独自の実装でノードコレクションを置き換えて、追加のプロパティを追加する独自の拡張System.Windows.Forms.TreeNodeを使用できるようにしました。拡張されたプロセスは、TreeNodeを追加するときに設計時にUIに反映されないという事実を除いて、かなりうまく機能します。私はプロパティをうまく変更することができますが、エディタウィンドウから大丈夫になるとすぐに、変更はインターフェイスに保持されません。デザイナーコードに追加が表示されますが、インターフェイスには何も表示されません。私はこれを成功させるための参考として、以下を使用しています。デザイン時にTreeNodeのTreeNodeCollectionをコードに永続化するにはどうすればよいですか?

http://windowsclient.net/blogs/faqs/archive/2006/05/26/how-do-i-persist-a-collection-of-items-into-code-at-design-time.aspx

http://support.microsoft.com/kb/322937

私は何かが欠けている必要があります。私は、これがwinformsコントロールを拡張するのが難しいとは思っていませんでした。ご協力いただきありがとうございます。気をつけて、素晴らしい一日を。

walkins5

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace ExtendedTreeViewControls 
{ 
    public class ComplexTreeNodeEditor : System.ComponentModel.Design.CollectionEditor 
    { 
     private CollectionForm collectionForm; 

     public ComplexTreeNodeEditor(Type type) : base(type) { } 

     public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
     { 
      if (this.collectionForm != null && this.collectionForm.Visible) 
      { 
       ComplexTreeNodeEditor editor = new ComplexTreeNodeEditor(this.CollectionType); 
       return editor.EditValue(context, provider, value); 
      } 
      else 
      { 
       return base.EditValue(context, provider, value); 
      } 
     } 

     protected override CollectionForm CreateCollectionForm() 
     { 
      this.collectionForm = base.CreateCollectionForm(); 
      return this.collectionForm; 
     } 
     protected override object CreateInstance(Type itemType) 
     { 
      TreeNodeEx tn = (TreeNodeEx)base.CreateInstance(itemType); 
      if (this.Context.Instance != null) 
      { 
       if (this.Context.Instance is ISupportUniqueName) 
       { 
        tn.Name = ((ISupportUniqueName)this.Context.Instance).GetUniqueName(); 
       } 
       else 
       { 
        tn.Name = "TreeNode"; 
       } 
      } 

      return tn; 
     } 
    } 
} 


using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.ComponentModel.Design.Serialization; 
using System.Globalization; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace ExtendedTreeViewControls 
{ 
    public class TreeNodeCollectionConverter : System.ComponentModel.ExpandableObjectConverter 
    { 
     #region Constructors 
     #endregion 

     #region Overrides 
     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
     { 
      if (sourceType.Equals(typeof(string))) 
      { 
       return true; 
      } 
      else 
      { 
       return base.CanConvertFrom(context, sourceType); 
      } 
      //return base.CanConvertFrom(context, sourceType); 
     } 
     public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
     { 
      if (destinationType == typeof(InstanceDescriptor)) 
      { 
       return true; 
      } 
      return base.CanConvertTo(context, destinationType); 

      //if (destinationType.Equals(typeof(string))) 
      //{ 
      // return true; 
      //} 
      //else 
      //{ 
      // return base.CanConvertTo(context, destinationType); 
      //} 
      ////return base.CanConvertTo(context, destinationType); 
     } 
     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
     { 
      if (value.GetType() == typeof(string)) 
      { 
       string txt = (string)value; 
       return null;//new TreeNodeCollection();//(txt); 
      } 
      else 
      { 
       return base.ConvertFrom(context, culture, value); 
      } 
      //return base.ConvertFrom(context, culture, value); 
     } 
     public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
     { 
      if (destinationType == typeof(InstanceDescriptor)) 
      { 
       System.Reflection.ConstructorInfo ci = 
        typeof(TreeNodeEx).GetConstructor(
        System.Type.EmptyTypes); 

       return new InstanceDescriptor(ci, null, false); 
      } 

      return base.ConvertTo(context, culture, value, destinationType); 

      //if (destinationType == typeof(string)) 
      //{ 
      // if (value is ICollection) 
      //  return "(Nodes)"; 
      //} 
      //else if (destinationType == typeof(InstanceDescriptor)) 
      //{ 
      // return new InstanceDescriptor(typeof(TreeNodeEx).GetConstructor(new Type[] { typeof(int), typeof(string), typeof(TreeNodeEx[]) }), new object[] { ((TreeNodeEx)value).Name, ((TreeNodeEx)value).Name }, true); 
      //} 

      //return base.ConvertTo(context, culture, value, destinationType); 
     } 
     public override bool GetPropertiesSupported(ITypeDescriptorContext context) 
     { 
      //return true; 
      bool tb = base.GetPropertiesSupported(context); 
      return tb; 
     } 
     public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
     { 
      PropertyDescriptorCollection col = TypeDescriptor.GetProperties(value); 
      return col; 
      //return base.GetProperties(context, value, attributes); 
     } 
     #endregion 
    } 
} 


using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace ExtendedTreeViewControls 
{ 
    [TypeConverter(typeof(TreeNodeCollectionConverter))] 
    public class TreeNodeCollectionEx : System.Collections.CollectionBase, IEnumerable 
    { 
     #region Events 
     /// <summary> 
     /// Raised when the collection changes. 
     /// </summary> 
     public event EventHandler Changed; 
     #endregion 

     #region Class Variables 
     // Back reference to the parent control 
     private TreeView parentTree = null; 
     #endregion 

     #region Constructors 
     /// <summary> 
     /// Initializes a new instance of the TreeNodeCollection using the parent bar. 
     /// </summary> 
     /// <param name="parentTree"></param> 
     public TreeNodeCollectionEx(TreeView parentTree) 
     { 
      this.parentTree = parentTree; 
     } 
     #endregion 

     #region Methods 

     /// <summary> 
     /// Adds a TreeNode to the collection. 
     /// </summary> 
     /// <param name="node">TreeNode to add.</param> 
     /// <returns>Index of the TreeNode just added in the collection.</returns> 
     public int Add(TreeNodeEx node) 
     { 

      if (Contains(node)) return -1; 
      int index = InnerList.Add(node); 
      RaiseChanged(); 
      return index; 
     } 


     /// <summary> 
     /// Adds a range of TreeNodes to the collection. 
     /// </summary> 
     /// <param name="nodes">Array of TreeNodes</param> 
     public void AddRange(TreeNodeEx[] nodes) 
     { 
      // Add the array 
      for (int i = 0; i < nodes.Length; i++) 
      { 
       Add(nodes[i]); 
      } 
     } 


     /// <summary> 
     /// Method to determine if the passed TreeNode is contained in the collection. 
     /// </summary> 
     /// <param name="node">TreeNode to test.</param> 
     /// <returns>True if the TreeNode is in the collection.</returns> 
     public bool Contains(TreeNodeEx node) 
     { 
      return InnerList.Contains(node); 
     } 


     /// <summary> 
     /// Method to obtain the index of a TreeNode in the collection. 
     /// </summary> 
     /// <param name="node">TreeNode</param> 
     /// <returns>Index of the TreeNode in the collection.</returns> 
     public int IndexOf(TreeNodeEx node) 
     { 
      return InnerList.IndexOf(node); 
     } 


     /// <summary> 
     /// Removes a TreeNode from the collection. 
     /// </summary> 
     /// <param name="node">The TreeNode to remove.</param> 
     public void Remove(TreeNodeEx node) 
     { 
      if (InnerList.Contains(node)) 
      { 
       InnerList.Remove(node); 
       RaiseChanged(); 
      } 
     } 


     /// <summary> 
     /// Inserts a TreeNode in a specific location. 
     /// </summary> 
     /// <param name="index">Index in the collection where the TreeNode should be inserted.</param> 
     /// <param name="node">TreeNode</param> 
     public void Insert(int index, TreeNodeEx node) 
     { 
      // Delegate to base class 
      InnerList.Insert(index, node); 
      RaiseChanged(); 
     } 

     /// <summary> 
     /// Gets the TreeNode whose index is passed. 
     /// </summary> 
     public TreeNodeEx this[int index] 
     { 
      get 
      { 
       if (index < 0 || index >= Count) 
        return null; 
       return (TreeNodeEx)InnerList[index]; 
      } 
     } 
     public TreeNodeEx[] GetValues() 
     { 
      //It is used by the ComplexItemConverter 
      TreeNodeEx[] ci = new TreeNodeEx[this.InnerList.Count]; 
      this.InnerList.CopyTo(0, ci, 0, this.InnerList.Count); 
      return ci; 
     } 

     #endregion 

     #region Implementation 
     void RaiseChanged() 
     { 
      if (Changed != null) Changed(this, null); 
     } 
     #endregion 
    } 
} 
+0

我々はいくつかのコードを参照する必要があります。標準のTreeNodeで動作する場合、tagプロパティを使用して追加のプロパティを持つカスタムオブジェクトを格納する方が簡単です。 –

+0

UIを構築するときに開発者が使用する複数のプロパティを持つカスタムコントロールを構築するとき、tagプロパティはそれほど役に立ちません。私はいくつかのコードを表示するのが大好きですが、私は複数のクラスファイルを持っていて、このサイトでそれらをどのように表現するかについてはあまりよく分かりません。問題となるかもしれないコードの主な部分は、私が使用しているSystem.ComponentModel.Design.CollectionEditorだと思っています。 – WalkSolutions

答えて

2

さて、

私はついにそれを考え出しました。基本的に元のTreeNodeCollectionクラスのラッパーであるTreeNodeCollectionの独自の実装を作成することに成功したことが判明しました。私はTreeNodeConverter ConvertToメソッドを構築して、すべてのTreeNodeを適切なフォーマットに構成しました。デザインタイムにTreeViewを作成してツリーノードを追加すると、プロパティを変更してすべての変更をフォームデザイナーに残すことができます。将来これに直面する可能性のある他の人を助けるためのコード。気をつけて、素晴らしい一日を。

TreeNodeCollectionクラス

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Reflection; 
using System.Globalization; 

namespace ExtendControls 
{ 
    [TypeConverter(typeof(MenuTreeNodeConverter))] 
    public class MenuTreeNodeCollection : IList, ICollection, IEnumerable 
    { 
     private TreeNode _owner; 
     private TreeNodeCollection _collection; 

     internal MenuTreeNodeCollection(TreeNode owner) 
     { 
      _owner = owner; 
     } 

     internal TreeNodeCollection Collection 
     { 
      set { _collection = value; } 
     } 

     internal int FixedIndex 
     { 
      get 
      { 
       return (int)_collection.GetType().GetProperty("FixedIndex", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_collection, null); 
      } 
      set 
      { 
       _collection.GetType().GetProperty("FixedIndex", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(_collection, value, null); 
      } 
     } 

     public virtual TreeNode this[int index] 
     { 
      get 
      { 
       return _collection[index]; 
      } 
      set 
      { 
       _collection[index] = value; 
      } 
     } 

     object IList.this[int index] 
     { 
      get 
      { 
       return this[index]; 
      } 
      set 
      { 
       if (value is TreeNode) 
       { 
        this[index] = (TreeNode)value; 
       } 
       else 
       { 
        //throw new ArgumentException(SR.GetString(SR.TreeNodeCollectionBadTreeNode), "value"); 
       } 
      } 
     } 

     public virtual TreeNode this[string key] 
     { 
      get 
      { 
       return _collection[key]; 
      } 
     } 
     [Browsable(false)] 
     public int Count 
     { 
      get 
      { 
       return _collection.Count; 
      } 
     } 

     object ICollection.SyncRoot 
     { 
      get 
      { 
       return _collection; 
      } 
     } 

     bool ICollection.IsSynchronized 
     { 
      get 
      { 
       return false; 
      } 
     } 

     bool IList.IsFixedSize 
     { 
      get 
      { 
       return false; 
      } 
     } 

     public bool IsReadOnly 
     { 
      get 
      { 
       return false; 
      } 
     } 

     public virtual TreeNode Add(string text) 
     { 
      return _collection.Add(text); 
     } 

     public virtual TreeNode Add(string key, string text) 
     { 
      return _collection.Add(key, text); 
     } 

     public virtual TreeNode Add(string key, string text, int imageIndex) 
     { 
      return _collection.Add(key, text, imageIndex); 
     } 

     public virtual TreeNode Add(string key, string text, string imageKey) 
     { 
      return _collection.Add(key, text, imageKey); 
     } 

     public virtual TreeNode Add(string key, string text, int imageIndex, int selectedImageIndex) 
     { 
      return _collection.Add(key, text, imageIndex, selectedImageIndex); 
     } 

     public virtual TreeNode Add(string key, string text, string imageKey, string selectedImageKey) 
     { 
      return _collection.Add(key, text, imageKey, selectedImageKey); 
     } 

     public virtual void AddRange(TreeNode[] nodes) 
     { 
      _collection.AddRange(nodes); 
     } 

     public TreeNode[] Find(string key, bool searchAllChildren) 
     { 
      return _collection.Find(key, searchAllChildren); 
     } 

     private ArrayList FindInternal(string key, bool searchAllChildren, MenuTreeNodeCollection treeNodeCollectionToLookIn, ArrayList foundTreeNodes) 
     { 
      MethodInfo mi = _collection.GetType().BaseType.GetMethod("FindInternal", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
      if (mi != null) 
      { 
       return (ArrayList)mi.Invoke(_collection, new object[] { key, searchAllChildren, treeNodeCollectionToLookIn, foundTreeNodes }); 
      } 
      return null; 
     } 

     private ArrayList FindInternal(string key, bool searchAllChildren, TreeNodeCollection treeNodeCollectionToLookIn, ArrayList foundTreeNodes) 
     { 
      MethodInfo mi = _collection.GetType().BaseType.GetMethod("FindInternal", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
      if (mi != null) 
      { 
       return (ArrayList)mi.Invoke(_collection, new object[] { key, searchAllChildren, treeNodeCollectionToLookIn, foundTreeNodes }); 
      } 
      return null; 
     } 

     public virtual int Add(TreeNode node) 
     { 
      return _collection.Add(node); 
     } 

     private int AddInternal(TreeNode node, int delta) 
     { 
      MethodInfo mi = _collection.GetType().BaseType.GetMethod("AddInternal", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
      if (mi != null) 
      { 
       return (int)mi.Invoke(_collection, new object[] { node, delta }); 
      } 
      return 0; 
     } 

     int IList.Add(object node) 
     { 
      if (node == null) 
      { 
       throw new ArgumentNullException("node"); 
      } 
      else if (node is TreeNode) 
      { 
       return _collection.Add((TreeNode) node); 
      } 
      else 
      { 
       TreeNode tempNode = Add(node.ToString()); 
       return _collection.Add(tempNode); 
      } 
     } 

     public bool Contains(TreeNode node) 
     { 
      return _collection.Contains(node); 
     } 

     public virtual bool ContainsKey(string key) 
     { 
      return _collection.ContainsKey(key); 
     } 

     bool IList.Contains(object node) 
     { 
      if (node is TreeNode) 
      { 
       return _collection.Contains((TreeNode)node); 
      } 
      else 
      { 
       return false; 
      } 
     } 

     public int IndexOf(TreeNode node) 
     { 
      for (int index = 0; index < Count; ++index) 
      { 
       if (this[index] == node) 
       { 
        return index; 
       } 
      } 
      return -1; 
     } 

     int IList.IndexOf(object node) 
     { 
      if (node is TreeNode) 
      { 
       return _collection.IndexOf((TreeNode) node); 
      } 
      else 
      { 
       return -1; 
      } 
     } 

     public virtual int IndexOfKey(String key) 
     { 
      return _collection.IndexOfKey(key); 
     } 

     public virtual void Insert(int index, TreeNode node) 
     { 
      _collection.Insert(index, node); 
     } 

     void IList.Insert(int index, object node) 
     { 
      if (node is TreeNode) 
      { 
       _collection.Insert(index, (TreeNode) node); 
      } 
      else 
      { 
       throw new ArgumentException(/*SR.GetString(SR.TreeNodeCollectionBadTreeNode)*/"Bad TreeNode", "node"); 
      } 
     } 

     public virtual TreeNode Insert(int index, string text) 
     { 
      return _collection.Insert(index, text); 
     } 

     public virtual TreeNode Insert(int index, string key, string text) 
     { 
      return _collection.Insert(index, key, text); 
     } 

     public virtual TreeNode Insert(int index, string key, string text, int imageIndex) 
     { 
      return _collection.Insert(index, key, text, imageIndex); 
     } 

     public virtual TreeNode Insert(int index, string key, string text, string imageKey) 
     { 
      return _collection.Insert(index, key, text, imageKey); 
     } 

     public virtual TreeNode Insert(int index, string key, string text, int imageIndex, int selectedImageIndex) 
     { 
      return _collection.Insert(index, key, text, imageIndex, selectedImageIndex); 
     } 

     public virtual TreeNode Insert(int index, string key, string text, string imageKey, string selectedImageKey) 
     { 
      return _collection.Insert(index, key, text, imageKey, selectedImageKey); 
     } 

     private bool IsValidIndex(int index) 
     { 
      return ((index >= 0) && (index < this.Count)); 
     } 

     public virtual void Clear() 
     { 
      _collection.Clear(); 
     } 

     public void CopyTo(Array dest, int index) 
     { 
      _collection.CopyTo(dest, index); 
     } 

     public void Remove(TreeNode node) 
     { 
      _collection.Remove(node); 
     } 

     void IList.Remove(object node) 
     { 
      if (node is TreeNode) 
      { 
       _collection.Remove((TreeNode)node); 
      } 
     } 

     public virtual void RemoveAt(int index) 
     { 
      this[index].Remove(); 
     } 

     public virtual void RemoveByKey(string key) 
     { 
      _collection.RemoveByKey(key); 
     } 

     public IEnumerator GetEnumerator() 
     { 
      return _collection.GetEnumerator(); 
     } 
    } 
} 

TreeNodeConverterクラス

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.ComponentModel.Design.Serialization; 
using System.Globalization; 
using System.Linq; 
using System.Reflection; 
using System.Text; 

namespace ExtendControls 
{ 
    public class MenuTreeNodeConverter : TypeConverter 
    { 
     public override bool CanConvertFrom(ITypeDescriptorContext context, Type type) 
     { 
      if (type == typeof(string)) 
      { 
       return true; 
      } 

      return base.CanConvertFrom(context, type); 
     } 

     public override bool CanConvertTo(ITypeDescriptorContext context, Type type) 
     { 
      if (type == typeof(InstanceDescriptor) || type == typeof(string)) 
      { 
       return true; 
      } 

      return base.CanConvertTo(context, type); 
     } 

     public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo info, object value) 
     { 
      if (value != null && value is string) 
      { 
       string[] items = ((string)value).Split(','); 
       return new MenuTreeNode(items[0], items[1]); 
      } 

      return base.ConvertFrom(context, info, value); 
     } 

     public override object ConvertTo(ITypeDescriptorContext context, CultureInfo info, object value, Type type) 
     { 
      if (type == null) 
      { 
       throw new ArgumentNullException("type"); 
      } 
      if ((type == typeof(InstanceDescriptor)) && (value is MenuTreeNode)) 
      { 
       MenuTreeNode node = (MenuTreeNode)value; 
       MemberInfo member = null; 
       object[] arguments = null; 
       if ((node.ImageIndex == -1) || (node.SelectedImageIndex == -1)) 
       { 
        if (node.Nodes.Count == 0) 
        { 
         member = typeof(MenuTreeNode).GetConstructor(new Type[] { typeof(string) }); 
         arguments = new object[] { node.Text }; 
        } 
        else 
        { 
         member = typeof(MenuTreeNode).GetConstructor(new Type[] { typeof(string), typeof(MenuTreeNode[]) }); 
         MenuTreeNode[] dest = new MenuTreeNode[node.Nodes.Count]; 
         node.Nodes.CopyTo(dest, 0); 
         arguments = new object[] { node.Text, dest }; 
        } 
       } 
       else if (node.Nodes.Count == 0) 
       { 
        member = typeof(MenuTreeNode).GetConstructor(new Type[] { typeof(string), typeof(int), typeof(int) }); 
        arguments = new object[] { node.Text, node.ImageIndex, node.SelectedImageIndex }; 
       } 
       else 
       { 
        member = typeof(MenuTreeNode).GetConstructor(new Type[] { typeof(string), typeof(int), typeof(int), typeof(MenuTreeNode[]) }); 
        MenuTreeNode[] nodeArray2 = new MenuTreeNode[node.Nodes.Count]; 
        node.Nodes.CopyTo(nodeArray2, 0); 
        arguments = new object[] { node.Text, node.ImageIndex, node.SelectedImageIndex, nodeArray2 }; 
       } 
       if (member != null) 
       { 
        return new InstanceDescriptor(member, arguments, false); 
       } 
      } 
      else if ((type == typeof(InstanceDescriptor)) && (value is MenuTreeNodeCollection)) 
      { 
       Type valueType = value.GetType(); 
       ConstructorInfo ci = valueType.GetConstructor(System.Type.EmptyTypes); 
       return new InstanceDescriptor(ci, null, false); 
      } 
      else 
      { 
       Type valueType = value.GetType(); 
       ConstructorInfo ci = valueType.GetConstructor(System.Type.EmptyTypes); 
       return new InstanceDescriptor(ci, null, false); 
      } 
      return base.ConvertTo(context, info, value, type); 
     } 
    } 
} 
関連する問題