Mittwoch, 21. Dezember 2011

C# - Einfacher Zugriff von einem Benutzersteuerelement auf das übergeordnete Formular

Wie bereits angedroht verwende ich diesen Blog für alles was mir gerade so einfällt. Und damit es nicht langweilig wird gibt es heute mal ein kleines C# Tutorial.

Die Voraussetzungen hierfür ist eine C# Entwicklungsumgebung. (z.B. Visual Studio 2010)

In diesem Tutorial beschäftigen wir und mit einem Problem was mir diese Woche zum ersten mal über den Weg gelaufen ist. Das Problem ist dass man von einem Benutzersteuerelement nicht direkt auf die Member der Instanz des übergeordneten Formulares zugreifen kann. Da wir nicht einfach auf das Objekt zugreifen können und so nur statische Member erreichbar sind (die uns nichts nützen, wenn wir zum Beispiel auf andere Steuerelemente zugreifen wollen), müsste man mit einem Zeiger (Pointer) auf das Formular verweisen.
C# verfügt aber leider nur über eingeschränke Möglichkeiten um mit Zeigern zu arbeiten. Das verweisen auf Objekte von Klassen ist zum Beispiel nicht möglich... naja zumindest nicht im eigentlichen Sinne.

Dass das auf eine sehr ähnliche Art trotzdem funktioniert will ich euch heute zeigen.
(Für die erfahrenen Coder: Sorry dass ich hier alles Schritt für Schritt erkläre, aber das Tutorial richtet sich auch an die die noch nicht so viel Erfahrung mit C# gesammelt haben)

Dann mal ran an den Speck:

Erstellt mit eurer Entwicklungsumgebung eine neue Windows-Forms-Anwendung. Ich nenne dieses Projekt SimpleAsAPointer.

"Neues Projekt"-Dialog im Visual Studio 2010

Geht nun auf dem Projektmappen-Explorer und klickt mit der rechten Maustaste auf euer Projekt. Wählt Hinzufügen, dann Benutzersteuerelement... und klickt auf hinzufügen. (Ihr könnt dem auch noch einen sinnvollen Namen geben; Ich nehm in dem Beispiel den vorgeschlagenen Namen UserControl1)

Damit das sich das Element optisch noch vom Formular abhebt, setze ich die BorderStyle-Eigenschaft noch auf FixedSingle und die BackColor auf LightGreen. Außerdem füge ich einen Button zum Steuerelement hinzu. Das kann man entweder bequem in der Entwurfsansicht des UserControl1 (Die Eigenschaften im Eigenschaften-Fenster anpassen und den Button von der Toolbox aus per Drag'n'Drop auf das Element ziehen) oder im Quelltext erledigen.

UserControl1.cs
 using System;
 using System.Drawing;  
 using System.Windows.Forms;  
 namespace SimpleAsAPointer  
 {  
   public partial class UserControl1 : UserControl  
   {  
     public UserControl1()  
     {  
       InitializeComponent();  
       // Eigenschaften setzen
       this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
       this.BackColor = Color.LightGreen;
       // Button hinzufügen
       Button button1 = new Button();
       button1.Text = "Klick mich";
       button1.Location = new Point(10, 10);
       button1.BackColor = Color.LightYellow;
       this.Controls.Add(button1);  
     }  
   }  
 }  
Es wird ein neues Button-Objekt button1 erzeugt. Bevor es zu den Controls des Benutzersteuerelements UserControl1 hinzugefügt wird, wird noch die Text-Eigenschaft auf "Klick mich", die Hintergrundfarbe auf LightYellow und die Position festgelegt.

Nun fügen wir das UserControl1 und eine TextBox (Auf die wir später zugreifen wollen) zu unserem Hauptformular Form1 hinzu. Das kann man wieder über die Entwurfsansicht von Form1 (Eigene Benutzersteuerelemente werden erst in der Toolbox verfügbar, wenn man das Projekt bereits erstellt hat! Zum erstellen: Rechtsklick auf das Projekt im Projektmappenexplorer und dann auf Erstellen oder Neu erstellen klicken) oder direkt im Code tun.

Form1.cs
 using System.Drawing;  
 using System.Windows.Forms;  
 namespace SimpleAsAPointer  
 {  
   public partial class Form1 : Form  
   {  
     public TextBox txtBx;  

     public Form1()  
     {  
       InitializeComponent();  
       // Hinzufügen des Benutzersteuerelements  
       UserControl1 usrCtr = new UserControl1();  
       usrCtr.Location = new Point(10, 10);  
       this.Controls.Add(usrCtr);  
       // Hinzufügen einer TextBox  
       txtBx = new TextBox();  
       txtBx.Location = new Point(10, 170);  
       this.Controls.Add(txtBx);  
     }  
   }  
 }  
Zunächst wird ein öffentliches (public) Objekt einer TextBox erstellt, dieses nennen wir txtBx. Danach setzen wir (ähnlich wie bei UserControl.cs) ein paar Eigenschaften und fügen die TextBox und ein Objekt des UserControl1 (usrCtr) zu den Steuerelementen des Formulars hinzu.

Somit wäre der erste Teil geschaft und die Oberfläche der Anwendung sollte nun wie folgt aussehen:

Oberfläche der Testanwendung
Nun fehlt nur noch eine sinnvolle Funktion. In unserem Beispiel soll beim klicken des button1 die aktuelle Uhrzeit in die txtBx geschrieben werden. Da sich der Button aber in einem untergeordneten Benutzersteuerelement befindet können wir dies nur realisieren in dem wir einen "Quasi-Pointer" im Element UserControl1 erzeugen. Quasi-Pointer desshalb, da es praktisch wie ein Zeiger funktioniert, theoretisch aber eigentlich keiner ist. (Zumindest wird er anders definiert)

Verwirrt? Macht nichts, es ist eigentlich ganz einfach.

UserControl1.cs
 using System;
 using System.Drawing;  
 using System.Windows.Forms;  
 namespace SimpleAsAPointer  
 {  
   public partial class UserControl1 : UserControl  
   {  
     public Form1 formPointer;  

     public UserControl1()  
     {  
       InitializeComponent();  
       // Eigenschaften setzen  
       this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;  
       this.BackColor = Color.LightGreen;  
       // Button hinzufügen  
       Button button1 = new Button();  
       button1.Text = "Klick mich";  
       button1.Location = new Point(10, 10);  
       button1.BackColor = Color.LightYellow;  
       this.Controls.Add(button1);  
     }  
   }  
 }  
Wir fügen zunächst zum UserControl1 ein öffentliches Objekt des Hauptformulares Form1 hinzu (formPointer). Das Objekt wird nicht konstruiert (verbleibt als null-Wert), da wir ja kein neues Formular erzeugen, sondern lediglich auf das bereits Vorhandene verweisen wollen.

Nun können wir den Verweis beim Erstellen des UserControl1 Objekts usrCtr im Form1 setzen.

Form1.cs
 using System.Drawing;  
 using System.Windows.Forms;  
 namespace SimpleAsAPointer  
 {  
   public partial class Form1 : Form  
   {  
     public Form1()  
     {  
       InitializeComponent();  
       // Hinzufügen des Benutzersteuerelements  
       UserControl1 usrCtr = new UserControl1();  
       usrCtr.formPointer = this;      
       usrCtr.Location = new Point(10, 10);  
       this.Controls.Add(usrCtr);  
       // Hinzufügen einer TextBox  
       TextBox txtBx = new TextBox();  
       txtBx.Location = new Point(10, 170);  
       this.Controls.Add(txtBx);  
     }  
   }  
 }  
Wir übergeben dem öffentlichen Member formPointer des usrCtr das Objekt des aktuellen Hauptformulars.

Somit steht der Verweis und wir können vom UserControl1 Objekt aus auf die Instanz-Member des übergeordneten Formulares zugreifen. YIPPIE-YA-YEAH! Um den Quasi-Pointer auf die Probe zu stellen, fügen wir jetzt ein Click-Event zum button1 hinzu.

UserControl1.cs
 using System;  
 using System.Drawing;  
 using System.Windows.Forms;  
 namespace SimpleAsAPointer  
 {  
   public partial class UserControl1 : UserControl  
   {  
     public Form1 formPointer;  

     public UserControl1()  
     {  
       InitializeComponent();  
       // Eigenschaften setzen  
       this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;  
       this.BackColor = Color.LightGreen;  
       // Button hinzufügen  
       Button button1 = new Button();  
       button1.Text = "Klick mich";  
       button1.Location = new Point(10, 10);  
       button1.BackColor = Color.LightYellow;  
       button1.Click += new EventHandler(button1_Click);  
       this.Controls.Add(button1);  
     }  

     private void button1_Click(object sender, EventArgs e)  
     {  
       formPointer.txtBx.Text = DateTime.Now.ToString("HH:mm:ss");  
     }    
   }  
 }  
Es wurde jetzt nur noch das Click-Event des button1 definiert und die Methode hinzugefügt, in der die Text-Eigenschaft der txtBx auf dem Hauptformular mit der derzeitigen Uhrzeit (DateTime.Now) aktualisiert wird.

So das wars dann auch schon. Wenn alles funktioniert, zeigt die TextBox beim klicken des Buttons die aktuelle Uhrzeit an!

Die Projektmappe gibt es hier zum Download!

Keine Kommentare:

Kommentar veröffentlichen