C# Finden einer Component?

roker002

Commander
Registriert
Dez. 2007
Beiträge
2.075
Ich habe das Problem... Ich muss eine Komponente finden und kein Control, also funktioniert da this.Controls.Find(...) nicht.

Diese Komponente gehört nicht zu der Hauptklasse die des Hauptforms. Diese sitzt in einem UserControl.

Ich habe schon nachgegoogelt aber finde immer noch nichts wie man eine Komponente ausfindig machen kann.

Danke
 
ein Control erbt von der Komponente... d.h. aber nicht dass man mit Controls.Find eine Komponente finden kann. Eine Componente ist kein Control... es ist z.B. MenuItem oder auch ein ToolTip. ToolTip selbst ist kein Control.

Das meinte ich mit Komponenten.
 
Ok verstehe, und wieso willst du diese Komponente finden? Was willst du denn erreichen, eventuell gibts ne andere Lösung.
 
@tueffi: Es wäre ja zu leicht für andere, sinnvollzu antworten, wenn er sagen würde, nach welchen Kriterien er sucht...
 
also... nach welchen Kriterien? da steht doch oben, dass ich als Referenz Controls.Find nehme. Heißt es nicht dass ich nach Namen suchen will?
 
Eine Componente in .Net hat nicht immer einen Namen. Manche Komponenten haben diese Property andere wiederum nicht. Das ganze wird aber nicht ersichtlich wenn man nur in den Visual Studio Designer unter den Properties nachschaut. Wenn du eine Komponente in einem UserControl suchst, dann kenne ich da nur den Weg über die Reflektion Klassen oder TypeDescriptor Klasse. Allgemein hat jedes UserControl/Form eine private Instanzvariable namens "components", welches ein Container ist, in dem alle Komponenten des UserControls enthalten sind, die nicht auf der Form greifbar sind. Aber bei diesen Components kannst du meist nur über den Typ rausfinden ob es die Componente evtl. sein könnte, die du suchst. Wie gesagt Namen haben die meistens nicht, auch wenn ein Name im Visual Studio Designer angegeben wird. Der Designer verwendet diesen Namen nur für interne Zwecke um die Variable für die Instanz eindeutig zu benennen und steht dann nur als Variablenname in der Form/UserControl zur Verfügung, z.B. die Timer Komponente.

Die ToolStripItems sind jedoch im ToolStrip unter der Property Items greifbar und implementieren eine Property Name die verwendet werden könnte. Das ist aber nicht bei jeder Komponente der Fall.

Als Alternative könntest du auch einen ExtendedPropertyProvider missbrauchen, um alle Komponenten einer Form zu registrieren und diesen dann durchsuchen. Dieser Extender hätte nicht die Beschränkung auf Controls und könnte als Public dann jederzeit seine registrierten Komponenten nach außen zur Verfügung stellen.
 
Also bist du nicht daran interessiert uns zu sagen was du machen willst das wir dir vielleicht einen anderen Weg bieten könnten, wenn wir wissen um was geht.
 
@toeffi: Eigentlich eine einfache Sache wenn ich roker verstehe: Er will über den Namen eine beliebige Komponente auf seiner Form finden. Für Controls ganz einfach, für Komponenten nicht ohne weiteres möglich.

@roker: Habs gerade mit einem ExtenderProvider probiert und das Ganze funktioniert auch. Also bei Interesse an der Klasse, sags einfach dann poste ich.
 
Zuletzt bearbeitet:
@rossibär!
Danke

So ist es... Ich habe eine Form das aus mehreren Schichten besteht. Es hat mehrere UserControl Elemente, und wenn ich jetzt, z.B., von dem TopLevelControl ausgehen und von da aus auf eine Bestimmte Komponente zugreifen will, so habe ich dann aber ohne weiteres keine Möglichkeit diese Komponente ausfindig zu machen. Ich dachte dass WinForm deshalb bei Komponenten die namen eintragen lässt, weil es damit später "Eindeutig" (aus der Sicht des Designers, da es im Designer nur Eindeutige Namen zulässig sind, was in der Realität gar nicht funktioniert) erkennbar ist, mit Hashcodes oder was auch immer.

@Rossibär, ja poste mal ruhig die Lösung. Mittlerweile habe ich es anders gelöst, aber diese Lösung ist ehe zweifelhaft. Ich habe das gesuchte Objekt einfach Global sichtbar gemacht. So mal ein Code Beispiel:

Code:
Class TopLevel
{
     ToolTip = null;
     public TopLevel()
     {
           ///InitComponent... dort wurde auch der unterer LevelControl initialisiert und hinzugefügt
           ToolTip = LowerLevelControl.ToolTip;
     }
}

schrecklich sowas, aber wenn man keine andere Chance hat oder kennt :D
 
@roker:

Hier die Solution (VS2005)

Anhang anzeigen GetAllComponents.zip

Wenn ich das richtig verstehe, dann musst du in jeder deiner UserControl Klassen die Komponente "ComponentFinder" (siehe Solution) im Designer hinzufügen. Ebenso solltest du auch in dem UserControl eine Property implementieren, die die ComponentFinder Instanz nach außen weiter gibt, sodaß du aus der Form heraus in den UserControls nach den Komponenten suchen kannst. Ist leider umständlich, wenn das was du suchst im UserControl steckt, da diese Standardmäßig nicht die Objekte nach außen sichtbar macht. Das Beispiel was ich habe, geht davon aus das sich alles auf der Form befindet, d.h. keine UserControls verwendet wurden.

Der Trick an der Sache ist, dass der Designer für jede Komponente im InitializeComponent einen Aufruf der Setter Methode des Extender Providers hinzufügt. D.h. wenn der Visual Studio Designer die Form oder das UserControl serialisiert, wird das ComponentFinder Objekt mit den entsprechenden Einträge für jede Komponente der UserControl Klasse gefüllt.

So gesehen ist es nicht die 100% Lösung die du wahrscheinlich suchst, aber zumindest ein Anfang mit dem du das Ziel erreichen könntest.

Viel Erfolg

PS: Der Designer benötigt für die einzelnen Komponenten einen Namen, da er selbst Code generiert der irgend eine Variable referenzieren muss um das Objekt dann auch richtig initialisieren zu können. Viele Komponenten haben keinen Namen. Es wird aber dennoch einer vom Designer benötigt, der dann als Variable in der Form definiert wird.
 
Zuletzt bearbeitet:
hm, ich habe noch nicht selbst ausprobiert, aber geht das auch während der Laufzeit? Ich meine wenn man viele Projekte einer Solution als ganzes Programm laufen lässt.
 
Der Trick bezog sich ausschließlich auf die Laufzeit und nutzt eine Vorgehensweise des Designer aus. Wenn du im Designer eine Form1 erstellst, dann erstellt der Designer im Hintergrund eine Form1.Designer.cs Datei in der er eine InitializeComponent() Methode reinsetzt. Diese Methode enthält alle Einstellungen die du für die einzelnen Objekte auf der Form getroffen hast, z.B. Text, Farbe, etc. als stink normalen C# Code. Diese Methode wird sowohl vom Designer als auch von der Form im Konstruktor aufgerufen um die Form mit ihren Objekten zu zeichnen. Das passiert in beiden Varianten, d.h. im Designer und während der Laufzeit. Der ComponentFinder von mir ist nichts weiter als ein Extender der für sich und alle anderen Komponenten auf der Form oder allgemein dem ParentControl die Namen und das Objekt selbst merkt und dann über die Methode "FindByName" die Instanz des Objektes an den Aufrufer zurückgibt.

Insgesamt bist du wahrscheinlich besser dran wenn du für jede zu setzende Eigenschaft der Komponenten im UserControl dann eine Property schreibst. Das wäre nur dann machbar wenn die Anzahl der notwendigen Properties überschaubar klein wäre. Andernfalls kannst du mit dem ComponentFinder dann generisch ALLE Komponenten während der Laufzeit über deren Namen ausfindig machen.

Viel Erfolg
Rossibaer
 
Zurück
Oben