Benutzer mit den meisten Antworten
Kann nicht auf controls einer usercontrol zugreifen

Frage
-
Hallo, ich möchte je nachdem welcher Button in meinem Projekt angeklickt wird im unteren teil meiner Form verschiedene usercontrols anzeigen.
Jetzt würde ich aber auch gerne vom Hauptform auf Variablen und textboxen des entsprechenden usercontrolls zugreifen können, weie geht das denn? bekomme das usercontroll irgendwie nicht angezeigt um z.B. so drauf zuzugreifen.
usercontrol1.textbox1.text = "HALLO";
geht das so nicht?
Antworten
-
Hallo B.,
Du hast mehrere Optionen:
1. Du änderst die Sichtbarkeit der Member, z.B. statt private textBox1, public textBox1 (würde ich nicht empfehlen)
2. Du erstellst eine öffentliche Eigenschaft, die den Zugriff auf den Member ermöglicht, z.B.:
public string Salutation {get {return textBox1.Text; } set {textBox1.Text = value;}}Zusätzlich könntest Du die Property Salutation über eine Schnittstelle nach außen präsentieren, womit die Bindung/Kopplung an die konkrete Klasse abgeschwächt und gelockert wird:
using System; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form, IMyInterface { public Form1() { InitializeComponent(); } public string Salutation {get {return textBox1.Text; } set {textBox1.Text = value;}} } public interface IMyInterface { string Salutation { get; set; } } }
Nun kannst Du aus deiner Form Code wie diesen schreiben:userControl1.Salutation = "Hey!";
bzw.:
IMyInterface myInterface = userControl1 as IMyInterface; myInterface.Salutation = "Hey!";
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Samstag, 15. Januar 2011 11:41
-
Hallo,
das geht nicht so. Das UserControl hat ja members, welche in der KLasse definert sind. Daher kannst Du auf untergeordnete Elemente nicht so zugreifen, wie auf Member der Klasse.
Die Controls, die in einem anderen Control enthalten sind, sind in einer Collection von Controls. Bei Windows Forms ist die Property Controls und bei WPF ist es wohl LogicalChildren.
Schau Dir einfach einmal die Control Classe des verwendeten Frameworks an und schau einmal die Property näher an. Dann solltest Du fündig werden.
Ansonsten gibt es bei WPF wohl auch eine Funktion, ein Control nach Namen zu suchen, aber das habe ich noch nicht gemacht.
Aber wenn Du die usercontrols selbst erstellst, dann kannst Du dem Usercontrol doch einfach neue Properties vergeben. Also z.B. TextBox1Text und in get /set holst du bzw. setzt textbox1.Text. Dann muss dein usercontrol1 nur von dem entsoprechend erstellten Typ sein und schon hast Du einfachen Zugriff drauf....
Damit solltest Du nun eine generische Lösung und eine individuelle Lösung per Design zur Hand haben.
Mit den besten Grüßen,
Konrad
- Als Antwort markiert Robert BreitenhoferModerator Samstag, 15. Januar 2011 11:41
-
Hallo B.,
- > das ist ja voll kompliziert, da muss ich ja für jedes Element in den
> user controlls noch was anlegen. wieso geht das denn nicht einfacher?
es geht sicher deutlich einfacher, obwohl der Ausdruck "einfach" immer relativ ist. .NET hat hier enorm viele Möglichkeiten.
Ich meine nicht unbedingt, dass Du die Hinweise in meinen folgenden Zeilen wirklich umsetzt, aber mein Posting ist da ein wenig allgemeiner verfasst, um die Möglichkeiten einmal aufzuzeigen.Aber zunächst will ich mal auf einen Punkt kommen, nämlich Objektorientierung. Man sollte das OOP Prinzip der Kapselung einhalten. Ich bin eher froh, dass das in .NET sauber unterstützt wird. Insofern wäre ein Zugriff auf private Variablen absolut unaktzeptabel.
Mit .NET (mit C#) kann man Dein Ansinnen auf verschiedene Arten lösen:- eigene DSL's. Letztlich gibst Du dann in Deiner domänen spezifischen Sprache nur noch die wichtigsten Elemente an und der Code wird automatisch erzeugt. Viel besser (einfacher) dann zum Beispiel, als hart codierte begrenzte frühere Frameworks. Dennoch hat man einen anfänglichen Aufwand, der einem dann allerdings später wiederum viel erspart.
- Nutzung von visueller Vererbung. Man baut seine Steuerelemente aus vorhandenen allgemein gültigeren zusammen.
- Nutzung von T4 Vorlagen. Ähnlich wie DSLs benutzt man quasi nur noch Platzhalter, woraus automatisch Code entsteht. Der Code ist dann in Deinem Fall die "Definition" der Controls.
Das ganze ist viel flexibler Versuche in anderen Frameworks.
Man kann auch bestehende UserControls mit t4 in gewünschte Formen transformieren. - Du mußt nicht unbedingt immer öffentliche Eigenschaften für Dein UserControl definieren, bzw. dass das "nicht" immer empfehlenswert - es ist je "nach Szenario" bei Steuerelementen durchaus ok, nur die Modifizierer public (oder eben nach oben sichtbar) zu machen, und pragmatisch ggf. vollkommen ok. Gut, das Thema ist durchaus auch kontrovers.
- Insgesamt ist man natürlich auch nicht auf Windows Forms angewiesen. WPF/Silverlight mit MEF bieten hier nochmals Vereinfachungen, weil die Trennung zwischen Darstellung und Logik besserunterstützt ist.
- Wir haben zum Beispiel Designer-Erweiterungen (allerdings in WPF/SL), die soetwas ermöglichen. Hier fliesst aber sicher ein erheblicher Aufwand in diese Erweiterungen und um das zu rechtfertigen muß das durch die späteren Erleichterungen mehr als hereingeholt werden, damit es sich lohnt.
- Es können Erweiterungsmethoden für UserControls erstellt werden, die ggf. viel Arbeit ersparen.
ok - das ganze ist sicher recht viel für jemand, der sich gerade einarbeitet, aber will man das Thema einigermaßen seriös beantworten, so sollten diese Punkte mindestens dabei sein, IMHO.
ciao Frank- Als Antwort markiert Robert BreitenhoferModerator Samstag, 15. Januar 2011 11:41
- > das ist ja voll kompliziert, da muss ich ja für jedes Element in den
Alle Antworten
-
Hallo B.,
Du hast mehrere Optionen:
1. Du änderst die Sichtbarkeit der Member, z.B. statt private textBox1, public textBox1 (würde ich nicht empfehlen)
2. Du erstellst eine öffentliche Eigenschaft, die den Zugriff auf den Member ermöglicht, z.B.:
public string Salutation {get {return textBox1.Text; } set {textBox1.Text = value;}}Zusätzlich könntest Du die Property Salutation über eine Schnittstelle nach außen präsentieren, womit die Bindung/Kopplung an die konkrete Klasse abgeschwächt und gelockert wird:
using System; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form, IMyInterface { public Form1() { InitializeComponent(); } public string Salutation {get {return textBox1.Text; } set {textBox1.Text = value;}} } public interface IMyInterface { string Salutation { get; set; } } }
Nun kannst Du aus deiner Form Code wie diesen schreiben:userControl1.Salutation = "Hey!";
bzw.:
IMyInterface myInterface = userControl1 as IMyInterface; myInterface.Salutation = "Hey!";
Gruß
Marcel- Als Antwort markiert Robert BreitenhoferModerator Samstag, 15. Januar 2011 11:41
-
Hallo,
das geht nicht so. Das UserControl hat ja members, welche in der KLasse definert sind. Daher kannst Du auf untergeordnete Elemente nicht so zugreifen, wie auf Member der Klasse.
Die Controls, die in einem anderen Control enthalten sind, sind in einer Collection von Controls. Bei Windows Forms ist die Property Controls und bei WPF ist es wohl LogicalChildren.
Schau Dir einfach einmal die Control Classe des verwendeten Frameworks an und schau einmal die Property näher an. Dann solltest Du fündig werden.
Ansonsten gibt es bei WPF wohl auch eine Funktion, ein Control nach Namen zu suchen, aber das habe ich noch nicht gemacht.
Aber wenn Du die usercontrols selbst erstellst, dann kannst Du dem Usercontrol doch einfach neue Properties vergeben. Also z.B. TextBox1Text und in get /set holst du bzw. setzt textbox1.Text. Dann muss dein usercontrol1 nur von dem entsoprechend erstellten Typ sein und schon hast Du einfachen Zugriff drauf....
Damit solltest Du nun eine generische Lösung und eine individuelle Lösung per Design zur Hand haben.
Mit den besten Grüßen,
Konrad
- Als Antwort markiert Robert BreitenhoferModerator Samstag, 15. Januar 2011 11:41
-
Seid mir nich tböse, aber das ist ja voll kompliziert, da muss ich ja für jedes Element in den user controlls noch was anlegen. wieso geht das denn nicht einfacher? So wie man auf ne deklaration ner klasse zugreift oder so. finde ich echt manchmal komisch, warum es bei manchen sachen so einfach geht und bei manchen dann wieder nur um 1000 ecken. da blick ich so einfach nicht durch :-(((
-
Hallo,
nunja, es ist nicht wirklich kompliziert und Marcel hat auch eine Lösung erwähnt, die recht einfach ist.
Also als erstes hast Du immer eine Klasse, die z.B. Dein Form definiert. Der Designer legt dort die ganzen Controls an. Wenn Du also einmal in das xxx.Designer.cs schaust, findest Du dort Zeilen wie:
private System.Windows.Forms.TextBox textBox1;Das bedeutet, dass die Klasse eine TextBox textBox1 bekommt, die nur für die Klasse selbst sichtbar ist. Also kannst Du da aus dieser Klasse drauf zugreifen (also z.B. per this.textBox1).
Das Gleiche hast Du dann auch in Deinem User-Control. Da es aber als privat deklariert ist, ist es erst einmal nicht direkt aus anderen Klassen (also z.B. deinem Formular) zugreifbar.
Dies kannst Du aber jederzeit anpassen, indem Du z.B. das private durch public ersetzt.
Andere Möglichkeiten gibt es aber auch. So findest Du z.B. folgende Zeile:
this.Controls.Add(this.textBox1);Alle Controls in einem Control müssen auch so einer Collection zugefügt werden. Diese Collection ist aber schon öffentlich erreichbar, daher mein Vorschlag, da einfach einmal drauf zuzugreifen. Dies hat den großen Vorteil, dass Du jedes Control nehmen kannst und es untersuchen kannst. Ich muss also Deine Klasse im Detail nicht kennen und kann dennoch die untergeordneten Controls auslesen.
Und mein zweiter Vorschlag war einfach, dass man vernünftige neue Properties erschafft. So ist z.B. folgendes Szenario Denkbar: Ich erstelle ein User-Controll "Address". In das Control tue ich Textboxes wie Name, Straße, PLZ, Ort u.s.w. Aus Sicht des Benutzers ist es egal, ob es TextBox-Klassen sind oder MaskedTextBox oder sonst irgendwas. Wichtig ist für einen Benutzer dieses Controls: er will es einfach plazieren und dann muss er die Adresse auslesen können also Properties wie Name, Street, City, ...
Hier geht es also um eine Kapselung. Durch die neuen Properties versteckt man die Details im Inneren, die auch egal sind (So kann ich das Control anpassen zu labels, die bei doppelclick erst eine Textbox einblenden zum ändern - und da nur auf die universellen properties zugegriffen wird, ist hier keine Anpassung notwendig!)Wenn Du einen einfachen Zugriff wie
usercontrol1.textbox1.text = "HALLO";
haben willst, ist aber evtl. tatsächlich ein einfacher Wechsel von private zu public ausreichend.
War die Erklärung soweit verständlich oder sollte noch irgendwas vertieft werden? Generell ist es eigentlich nicht wirklich kompliziert. (So sehe ich dies zumindestens. Das Problem ist wohl eher, dass die Erklärungen zu kurz waren oder so ...)
Mit den besten Grüßen,
Konrad
-
Hallo B.,
Seid mir nich tböse, aber das ist ja voll kompliziert, da muss ich ja für jedes Element in den user controlls noch was anlegen. wieso geht das denn nicht einfacher?
Wieso nicht einfacher? Die kurze Antwort ist "by design", weil - wie Konrad es bereits ausgeführt hat - ein UserControl eine eigenständige Klasse ist, die ihre Member kapselt und so vor dem Zugriff der Parent-Form schützt.
Aber so unrecht hast Du mit Deiner Frage nicht: Es könnte theoretisch auch einfacher gehen, wenn UserControl und das Framework nur etwas anders gestrickt wären... Ich weiß ja nicht, vielleicht kommst Du von Delphi und kennst das. Dort kann man z.B. seine UserControl-ähnliche Klasse von TFrame ableiten und diese über den IDE-Designer auf ein Formular plazieren und dann z.B. so etwas schreiben:
procedure TForm1.Button1Click(Sender: TObject);
begin
Frame1.Edit1.Text := 'Test';
end;(Eine ähnliche Syntax ist übrigens auch für MS Access Subformulare möglich.)
Leider gibt es dieses genaue Pendent zu TFrame in Windows.Forms nicht. Man könnte sich zwar so etwas wie eine partial class vorstellen, mit eigenem Designer-Support, d.h. selbstgebastelte UI-Bausteine, die im Hintergrund zu Code expandiert und transparent mit dem Code der Hautpform verschmelzt werden. Aber - wir müssen uns hier der Realität beugen - das alles ist z.Z. so mit dem .NET UserControl nicht realisierbar.Gruß
Marcel -
Hallo B.,
- > das ist ja voll kompliziert, da muss ich ja für jedes Element in den
> user controlls noch was anlegen. wieso geht das denn nicht einfacher?
es geht sicher deutlich einfacher, obwohl der Ausdruck "einfach" immer relativ ist. .NET hat hier enorm viele Möglichkeiten.
Ich meine nicht unbedingt, dass Du die Hinweise in meinen folgenden Zeilen wirklich umsetzt, aber mein Posting ist da ein wenig allgemeiner verfasst, um die Möglichkeiten einmal aufzuzeigen.Aber zunächst will ich mal auf einen Punkt kommen, nämlich Objektorientierung. Man sollte das OOP Prinzip der Kapselung einhalten. Ich bin eher froh, dass das in .NET sauber unterstützt wird. Insofern wäre ein Zugriff auf private Variablen absolut unaktzeptabel.
Mit .NET (mit C#) kann man Dein Ansinnen auf verschiedene Arten lösen:- eigene DSL's. Letztlich gibst Du dann in Deiner domänen spezifischen Sprache nur noch die wichtigsten Elemente an und der Code wird automatisch erzeugt. Viel besser (einfacher) dann zum Beispiel, als hart codierte begrenzte frühere Frameworks. Dennoch hat man einen anfänglichen Aufwand, der einem dann allerdings später wiederum viel erspart.
- Nutzung von visueller Vererbung. Man baut seine Steuerelemente aus vorhandenen allgemein gültigeren zusammen.
- Nutzung von T4 Vorlagen. Ähnlich wie DSLs benutzt man quasi nur noch Platzhalter, woraus automatisch Code entsteht. Der Code ist dann in Deinem Fall die "Definition" der Controls.
Das ganze ist viel flexibler Versuche in anderen Frameworks.
Man kann auch bestehende UserControls mit t4 in gewünschte Formen transformieren. - Du mußt nicht unbedingt immer öffentliche Eigenschaften für Dein UserControl definieren, bzw. dass das "nicht" immer empfehlenswert - es ist je "nach Szenario" bei Steuerelementen durchaus ok, nur die Modifizierer public (oder eben nach oben sichtbar) zu machen, und pragmatisch ggf. vollkommen ok. Gut, das Thema ist durchaus auch kontrovers.
- Insgesamt ist man natürlich auch nicht auf Windows Forms angewiesen. WPF/Silverlight mit MEF bieten hier nochmals Vereinfachungen, weil die Trennung zwischen Darstellung und Logik besserunterstützt ist.
- Wir haben zum Beispiel Designer-Erweiterungen (allerdings in WPF/SL), die soetwas ermöglichen. Hier fliesst aber sicher ein erheblicher Aufwand in diese Erweiterungen und um das zu rechtfertigen muß das durch die späteren Erleichterungen mehr als hereingeholt werden, damit es sich lohnt.
- Es können Erweiterungsmethoden für UserControls erstellt werden, die ggf. viel Arbeit ersparen.
ok - das ganze ist sicher recht viel für jemand, der sich gerade einarbeitet, aber will man das Thema einigermaßen seriös beantworten, so sollten diese Punkte mindestens dabei sein, IMHO.
ciao Frank- Als Antwort markiert Robert BreitenhoferModerator Samstag, 15. Januar 2011 11:41
- > das ist ja voll kompliziert, da muss ich ja für jedes Element in den