none
TreeNodeCollection ableiten RRS feed

  • Frage

  • Hi,

     

    ich habe mir eine ExtendedTreeView und eine ExtendedTreeNode Klasse geschrieben. Diese erben von System.Windows.Forms.TreeView bzw. System.Windows.Forms.TreeNode. 

     

    Nun hat die TreeView Klasse ein Property "Nodes" vom Typ TreeNodeCollection. Jedoch möchte ich an dieser Stelle direkt den Zugriff auf ExtendedTreeNodes ermöglichen ohne dass der Anwender dieses Controls einen Cast durchführen muss.

     

    Deshalb dachte ich mir ich schreibe eine ExtendedTreeNodeCollection Klasse, welche von TreeNodeCollection erbt. Das Problem: TreeNodeCollection hat keinen Constructor. Also kann ich davon auch nicht ableiten, richtig?

    Deshalb dachte ich mir ich lasse das erben von TreeNodeCollection weg und implementiere dafür (wie auch die TreeNodeCollection Klasse) die Interfaces ICollection, IList und IEnumerable. Das Problem: Ich kann in der ExtendedTreeView Klasse das Nodes Property nicht überschreiben, da die Datentypen nicht passen.

     

    Habe dann zuletzt versucht das Nodes Property zu verstecken und dafür ein anderes Property zu schreiben (beispielsweise ExtendedNodes), welche dann die ExtendedNodesCollection liefert. Das funktioniert aber auch nicht da ich Nodes (anscheinend) nicht überschreiben darf...

     

    Hat jemand irgendeine Idee wie ich das ganze lösen könnte?

     

    Gruß

    NbgSingh

     

     

    Dienstag, 9. August 2011 18:34

Antworten

  • Hallo N.,

    Du möchtest also in etwa diesen Code schreiben können:

    TreeNodeEx nodeEx1 = new TreeNodeEx("Node1");
    TreeNodeEx nodeEx2 = new TreeNodeEx("Node2");
    treeViewEx1.Nodes.AddRange(new TreeNodeEx[] { nodeEx1, nodeEx2 });
    TreeNodeCollectionEx nodes = treeViewEx1.Nodes; // kein Casten etc. notwendig
    

    Dazu mußt Du den Zugriff auf TreeView.Nodes so wrappen, dass die ursprüngliche Collection nicht mehr nach außen sichtbar ist, Operationen wie Add(), Remove() etc. aber weiterhin an die zugrunde liegende Collection geleitet werden:

    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Runtime.Serialization;
    
    namespace WindowsFormsApplication1 {
    
     class TreeViewEx : TreeView {
     TreeNodeCollectionEx _collection;
     public TreeViewEx() {
     _collection = new TreeNodeCollectionEx(base.Nodes);
     }
     // Wir "verstecken" die ursprüngliche Implementation
     public new TreeNodeCollectionEx Nodes { 
     // und geben unsere TreeNodeCollectionEx zurück
     get { return _collection; }
     }
     }
    
     // Hier könnten wir zusätzliche Methoden, Eigenschaften etc. implementieren
    class TreeNodeEx : TreeNode {
     public TreeNodeEx() { }
     public TreeNodeEx(string text) 
     : base(text) { }
     public TreeNodeEx(string text, TreeNode[] children)
     : base(text, children) { 
     }
    public TreeNodeEx(string text, int imageIndex, int selectedImageIndex)
     : base(text, imageIndex, selectedImageIndex) { }
     public TreeNodeEx(string text, int imageIndex, int selectedImageIndex, TreeNode[] children)
     : base(text, imageIndex, selectedImageIndex, children) { }
     protected TreeNodeEx(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context)
     : base(serializationInfo, context) { }
     }
    
    // Und das ist unser Ersatz für die TreeNodeCollection
    class TreeNodeCollectionEx : ICollection<TreeNodeEx> {
     TreeNodeCollection _baseCollection;
     public TreeNodeCollectionEx(TreeNodeCollection collection) {
     _baseCollection = collection;
     foreach(TreeNode node in collection) {
     TreeNodeEx nodeEx = node as TreeNodeEx;
     if(nodeEx != null)
      Add(nodeEx);
     }
     }
     public void AddRange(TreeNodeEx[] items) {
     _baseCollection.AddRange(items);
     }
     #region ICollection<TreeNodeEx> Member
     public void Add(TreeNodeEx item) {
     _baseCollection.Add(item);
     }
     public void Clear() {
     _baseCollection.Clear();
     }
     public bool Contains(TreeNodeEx item) {
     return _baseCollection.Contains(item);
     }
     public void CopyTo(TreeNodeEx[] array, int arrayIndex) {
     _baseCollection.CopyTo(array, arrayIndex);
     }
     public int Count {
     get { return _baseCollection.Count; }
     }
     public bool IsReadOnly {
     get { return _baseCollection.IsReadOnly; }
     }
     public bool Remove(TreeNodeEx item) {
     _baseCollection.Remove(item);
     return true;
     }
     #endregion
     #region IEnumerable<TreeNodeEx> Member
     public IEnumerator<TreeNodeEx> GetEnumerator() {
     return (IEnumerator<TreeNodeEx>)_baseCollection.GetEnumerator();
     }
     #endregion
     #region IEnumerable Member
     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
     return _baseCollection.GetEnumerator();
     }
     #endregion
     }
    }
    


    Natürlich ist der Beispiel-Code nur als Startpunkt zu verstehen.

    Gruß
    Marcel

    • Als Antwort markiert NbgSingh Freitag, 12. August 2011 22:59
    Donnerstag, 11. August 2011 08:31
    Moderator

Alle Antworten

  • Hi,

    kannst du den Code posten ? Ich kann deinen Erklärungen nicht folgen ;-)

    Also wie sehen Konkret deine Klassen aus.

    Grüße

    Mittwoch, 10. August 2011 06:50
  • Hallo Nb,

    folgendes erklärt dazu ein paar Dinge:

    [Inheriting or overriding a class within a class... why not?]
    http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/b1d575d3-9028-4946-a8dd-2e89316f51c3/

     


    ciao Frank
    Donnerstag, 11. August 2011 06:36
  • Hallo N.,

    Du möchtest also in etwa diesen Code schreiben können:

    TreeNodeEx nodeEx1 = new TreeNodeEx("Node1");
    TreeNodeEx nodeEx2 = new TreeNodeEx("Node2");
    treeViewEx1.Nodes.AddRange(new TreeNodeEx[] { nodeEx1, nodeEx2 });
    TreeNodeCollectionEx nodes = treeViewEx1.Nodes; // kein Casten etc. notwendig
    

    Dazu mußt Du den Zugriff auf TreeView.Nodes so wrappen, dass die ursprüngliche Collection nicht mehr nach außen sichtbar ist, Operationen wie Add(), Remove() etc. aber weiterhin an die zugrunde liegende Collection geleitet werden:

    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Runtime.Serialization;
    
    namespace WindowsFormsApplication1 {
    
     class TreeViewEx : TreeView {
     TreeNodeCollectionEx _collection;
     public TreeViewEx() {
     _collection = new TreeNodeCollectionEx(base.Nodes);
     }
     // Wir "verstecken" die ursprüngliche Implementation
     public new TreeNodeCollectionEx Nodes { 
     // und geben unsere TreeNodeCollectionEx zurück
     get { return _collection; }
     }
     }
    
     // Hier könnten wir zusätzliche Methoden, Eigenschaften etc. implementieren
    class TreeNodeEx : TreeNode {
     public TreeNodeEx() { }
     public TreeNodeEx(string text) 
     : base(text) { }
     public TreeNodeEx(string text, TreeNode[] children)
     : base(text, children) { 
     }
    public TreeNodeEx(string text, int imageIndex, int selectedImageIndex)
     : base(text, imageIndex, selectedImageIndex) { }
     public TreeNodeEx(string text, int imageIndex, int selectedImageIndex, TreeNode[] children)
     : base(text, imageIndex, selectedImageIndex, children) { }
     protected TreeNodeEx(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext context)
     : base(serializationInfo, context) { }
     }
    
    // Und das ist unser Ersatz für die TreeNodeCollection
    class TreeNodeCollectionEx : ICollection<TreeNodeEx> {
     TreeNodeCollection _baseCollection;
     public TreeNodeCollectionEx(TreeNodeCollection collection) {
     _baseCollection = collection;
     foreach(TreeNode node in collection) {
     TreeNodeEx nodeEx = node as TreeNodeEx;
     if(nodeEx != null)
      Add(nodeEx);
     }
     }
     public void AddRange(TreeNodeEx[] items) {
     _baseCollection.AddRange(items);
     }
     #region ICollection<TreeNodeEx> Member
     public void Add(TreeNodeEx item) {
     _baseCollection.Add(item);
     }
     public void Clear() {
     _baseCollection.Clear();
     }
     public bool Contains(TreeNodeEx item) {
     return _baseCollection.Contains(item);
     }
     public void CopyTo(TreeNodeEx[] array, int arrayIndex) {
     _baseCollection.CopyTo(array, arrayIndex);
     }
     public int Count {
     get { return _baseCollection.Count; }
     }
     public bool IsReadOnly {
     get { return _baseCollection.IsReadOnly; }
     }
     public bool Remove(TreeNodeEx item) {
     _baseCollection.Remove(item);
     return true;
     }
     #endregion
     #region IEnumerable<TreeNodeEx> Member
     public IEnumerator<TreeNodeEx> GetEnumerator() {
     return (IEnumerator<TreeNodeEx>)_baseCollection.GetEnumerator();
     }
     #endregion
     #region IEnumerable Member
     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
     return _baseCollection.GetEnumerator();
     }
     #endregion
     }
    }
    


    Natürlich ist der Beispiel-Code nur als Startpunkt zu verstehen.

    Gruß
    Marcel

    • Als Antwort markiert NbgSingh Freitag, 12. August 2011 22:59
    Donnerstag, 11. August 2011 08:31
    Moderator
  • Genau sowas habe ich gesucht. Super vielen Dank! Auch Danke an Frank für die Infoseite. :)
    Freitag, 12. August 2011 22:59
  • Hallo N.,

    > Genau sowas habe ich gesucht. Super vielen Dank!

    Gerne.

    Gruß
    Marcel

    Samstag, 13. August 2011 08:17
    Moderator