Laden...

Checkbox Status außerhalb der Form-Klasse auslesen

Erstellt von christof.k vor 19 Jahren Letzter Beitrag vor 19 Jahren 7.784 Views
C
christof.k Themenstarter:in
159 Beiträge seit 2005
vor 19 Jahren
Checkbox Status außerhalb der Form-Klasse auslesen

Hallo Zusammen,

ich möchte den Status einer Checkbox außerhalb der Klasse, in der die Checkbox definiert ist, auslesen.

Ich habe versucht, dies mit einer get() function zu lösen, doch der Compiler meldet, dass der this-Zeiger in einer statischen funktion nicht erlaubt ist.
Ich möchte die funktion aber statisch haben, da es keinen Sinn für mich macht, immer eine Instanz zu erstellen.

Welchen Weg kann ich nun einschlagen?

Vielen Dank
Christof

1.373 Beiträge seit 2004
vor 19 Jahren

Du brauchst so oder so eine Instanz der Form, da die checkbox nicht statisch ist.

Zwei Lösungen:

  1. die Methode/Klasse, die den Status der Checkbox auslesen soll, erhält eine Referenz auf die Form-Instanz
  2. du speicherst "irgendwo" die Form-Instanz in eine statische Variable

Die erste Lösung ist im Prinzip flexibler, da sie mit beliebig vielen Forms funktioniert.
Die zweite Methode lässt sich z.B. durch den Gebrauch des Singleton Patterns lösen. Aber NUR, wenn du ABSOLUT SICHER bist, dass die Form JETZ und in EWIGKEIT nur EINMAL (!) instanziert werden kann und darf - also gut darüber nachdenken! Alternativ kannst du eine statische Variable definieren, die eine "Standard" Instanz oder die aktive Form speichert, was allerdings zu sehr subtilen Fehlern führen kann.

Beide Konzepte werden nochmal deutlich eleganter und wartbarer, wenn du das MVC Pattern benutzt und statt direkt über die Form über das "Dokument" auf den Status der Checkbox, bzw. genauer: den Status des Schalters, den die Checkbox schaltet zugreifst.

Fazit: ich würde MVC benutzen und irgendwo das aktive Dokument als statische Variable hinterlegen (umgeschaltet wird es z.B. durch Umschalten zu einer View mit einem anderen Dokument). Die Methode, die den Zustand der Checkbox wissen will (btw. der Variable im Dokument, die die Checkbox schaltet), greift über die statische Variable auf das Dokument zu und muss so nichts von der Form wissen.

MfG VizOne

P
939 Beiträge seit 2003
vor 19 Jahren

Geht es um eine Form? Du müsstest die Form ja nicht ständig mit new neu erzeugen, sondern könntest sie aus einer Eigenschaft abrufen.

public class MyClass {

  public MyForm MyForm {
    // get; set;
  }

  public void ToggleChecked() {
    MyForm.CheckBox1.Checked = !MyForm.CheckBox1.Checked;
  }
}

wenn es unbedingt statisch sein soll:

public class MyClass {

  private static MyForm myForm;

  public static MyForm MyForm {
    get {
       if(MyClass.myForm == null) {
         MyClass.myForm = new MyForm();
       }
    }
  }
}

In der Form selbst würde ich keine statischen Member definieren. Ansonsten wird es schwierig, wenn doch einmal mehrere, gleiche Fenster angezeigt werden sollen.

Gruss
Pulpapex

C
christof.k Themenstarter:in
159 Beiträge seit 2005
vor 19 Jahren

Hallo,

dankeschön für die Antworten, aber da ich C# beginner bin, fehlt mir noch etwas die Handhabe.
Mein Form ist folgendermaßen definiert:

namespace MyApp
{
	public class MainForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.CheckBox cbMyCheckBox;

		public MainForm()
		{
			this.cbMyCheckBox = new System.Windows.Forms.CheckBox();
		}

		// Mein Versuch:
		public static bool CheckBoxSelected()
		{
			return this.cbMyCheckBox.Checked;	// hier bekomme ich einen Compilerfehler!
		}
	}
}

Mein Versuch der Readfunction gibt mir einen Compiler fehler. Nun stehe ich hier und kann Eure Hilfen leider nicht so direkt anwenden.
Ich möchte es wirklich einfach gestalten, da es nur um das Auslesen dieser Checkbox geht und ich vermute, dass es eine einfache Lösung gibt (oder? 🙂)

Vielen Dank schonmal für Eure Mühe
Christof

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo christof.k,

wenn sichergestellt ist, dass du nur ein MainForm-Objekt erzeugst und vor Benutzung von CheckBoxSelected das MainForm-Objekt erzeugt wurde, dann kannst du dass so machen (ohne Berücksichtigung von Fehlerbehandlung), aber schön ist das nicht:


namespace MyApp
{
    public class MainForm : System.Windows.Forms.Form
    {
        // die Variable ist jetzt auch static ...
        private static System.Windows.Forms.CheckBox cbMyCheckBox;

        public MainForm()
        {
            // deshalb steht hier auch kein this mehr
            cbMyCheckBox = new System.Windows.Forms.CheckBox();
        }

        public static bool CheckBoxSelected()
        {
            return cbMyCheckBox.Checked;
        }
    }
}

HTH

herbivore

C
christof.k Themenstarter:in
159 Beiträge seit 2005
vor 19 Jahren

Hallo,

das würde bei mir zwar zutreffen, aber natürlich bin ich auch an der sauberen Lösung interessiert.
Ich habe hier schon öfters von einer "Datenaustauschklasse" gelesen, die die Schnittstelle darstellt.
Leider ist mir nicht klar, wie ich das anstelle,...gibt es irgendwo ein Codebeispiel.
Wie gesagt, auch wenn ich gerade mit C# anfange liegt mir viel daran, von anfang an sauberen Code zu erzeugen.

Vielen Dank schonmal
Christof

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo christof.k,

wenn du jemanden eine Nachricht schicken willst, dann musst du nicht nur wissen, welche Nachricht du schicken willst, sondern auch an wen du sie schicken willst. Auf die Objekte bezogen ist die Nachricht CheckBoxSelected und der Empfänger ist das MainForm-Objekt, dass du vermutlich im Main mit new MainForm (); erzeugst.

Dass der Empfänger mindestens so wichtig ist, wie die Nachricht selbst, wird klar, wenn Du gedanklich mehrere MainForm-Objekte erzeugst (das mag in deinem Fall nicht beabsichtig sein, aber nimm als einen Beispiel einen Browser; da kannst du ja auch mehere (Haupt-)Fenster öffen). Und wenn es mehrere MainForm-Objekte gibt, dann gibt es mehrere CheckBoxen und die können natürlich auch gerade unterschiedlich gesetzt sein.

Also ändern wir den Code erstmal wieder so, dass jedes MainForm-Objekt seine eigene cbMyCheckBox-Variable (und auch seine eigene CheckBoxSelected-Methode) hat.


namespace MyApp
{
    public class MainForm : System.Windows.Forms.Form
    {
        private System.Windows.Forms.CheckBox cbMyCheckBox;

        public MainForm()
        {
            this.cbMyCheckBox = new System.Windows.Forms.CheckBox();
        }

        public bool CheckBoxSelected()
        {
            return cbMyCheckBox.Checked;
        }
    }
}

Dann musst du nur noch dafür sorgen, dass der Absender von CheckBoxSelected auch den Empfänger gekennt. Wie diese Information zum Absender kommt, hängt natürlich von Deinem restlichen Programm ab. Wenn dein MainForm-Objekt das andere Fenster erzeugt, dann könntest du z.B. den Konstruktor des anderen Fensters um einen Parameter vom Typ MainForm erweitern und beim Erzeugen this (von MainForm) als Parameter übergeben.

HTH

herbivore

P
939 Beiträge seit 2003
vor 19 Jahren

Hab nicht viel Zeit, deshalb nur Code:

public class MainForm : Form {

  private static MainForm instance ;
  private CheckBox checkBoxA;

  public static void Main() {
    Application.Run(new MainForm());
  }

  public MainForm() {
    MainForm.Instance = this;
  }

  public CheckBox CheckBoxA {
    get { return checkBoxA; }
  }

  // Einzige MainForm.
  private static MainForm Instance {
    get { return instance; }
    set { instance = value; }
  }

  // Statisch abrufbar.
  public static bool CheckBoxSelected {
    get { return Instance.CheckBoxA.Checked; }
  }
}
// Benutzung.
bool selected = MainForm.CheckBoxSelected;
C
christof.k Themenstarter:in
159 Beiträge seit 2005
vor 19 Jahren

Hallo,

mein Konstrukt sieht so aus, dass ich von einer anderen Klasse auf die Elemente meines Forms zugreifen möchte.

Ich würde nun gerne wissen, ob das i.O. ist, wie ich die Sache gelöst habe:

Ich habe zuerstmal Deinen Vorschlag eingearbeitet und dann in meiner Nicht-Form-Klasse eine static Variable definiert, die im Konstruktor des Forms mit dem this-Zeiger der Form initialisiert wird.

//In der Klasse:
public class HelpClass : MainForm
{
    public static MainForm localmainform;
....

// Im Konstruktor der Form:
HelpClass.localmainform = this;

Der Compiler ist zufrieden, die Frage ist nur, ob auch den Gedanken von Oop damit genüge getan ist.
Es ist richtig (denke ich), meine Klasse von der MainForm abzuleiten, da diese direkt davon abhängt.
Meine Frage ist, ob die Nutzung von static sauber ist.
Ich habe das in der Klasse fast durchgehend gemacht, da diese nicht mehrfach instanziert wird.

Vielen Dank schonmal im voraus!

Christof

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo christof.k,

nee, ich denke du bist noch nicht ganz auf dem richtigen Weg. Wenn deine Klasse HelpClass von MainForm erbt, dann hast du doch sowieso Zugriff auf die Instanzvariablen der Oberklasse - nagut, nur auf die, die protected sind, aber du kannst ja private in protected ändern. Du kannst also direkt die ComboBox ansprechen und musst keine weiteren Methoden definieren.

Wobei mich wundert, dass die HelpForm von MainForm erbt. Erzeugst Du denn nachher wirklich zwei Objekte oder nur eins vom Typ HelpClass?

Wenn Du nur ein Objekt erzeugst, dann brauchst du den ganzen Ramsch gar nicht, einfach protected statt private und direkt zugreifen.

Zwei Objekte erzeugst (ein MainForm und ein HelpClass) , dann ist deine Zuweisung im Konstruktor aber murx, da der Konstruktor von MainForm zweimal aufgerufen wird: einmal für das MainForm-Objekt, klar, und einmal für das HelpClass-Objekt, da ein HelpClass ja von MainForm erbt.

Wenn es wirklich zwei verschiedene Klassen sind, dann würde das so gehen (vorausgesetzt MainForm erzeugt das HelpClass-Objekt):


public class HelpClass
{
   public MainForm _mylocalmainform; // nicht static!

   HelpClass (MainForm mylocalmainform)
   {
      this._mylocalmainform = mylocalmainform;
   }
}

public class HelpClass
{
   //...

      // In der erzeugenden Methode
      new HelpClass (this);

   // ...
}

Also grundsätzlich: Mit static macht man eine Methode oder Variable zur Klassenmethode oder -variable. Dann gibt es die entsprechende Variable nur einmal pro Klasse und nicht einmal pro Objekt. Bei Klassen, von der es nur ein Objekt geben wird, ist das trozdem noch ein Unterschied, weil die Klassenvariabeln "immer" existieren und die Objektvariablen erst, nachdem das Objekt erzeugt wurde. Normalerweise braucht man nur Objektvariablen und ganz selten static-Variablen. Um etwas static zu machen, sollte man wollen, dass die Variable der Klasse gehört. Dies wäre z.B. der Fall, wenn man einen Zähler haben möchte, der der zählt, wieviele Objekte der Klasse schon erzeugt wurden. Denn muss man dann natürlich static machen. In Klassenvariablen speichert man also Informationen, die für alle Objekte gleich sind. Aber etwas static zu machen, weil man sonst nicht an die Information kommt ist murx.

HTH

herbivore