mikrocontroller.net

Forum: PC-Programmierung C# - Anfänger braucht Hilfe beim Umgang mit Klassen --> Zugriff auf Daten


Autor: Marco K. (mbc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute

Ich habe da ein ""kleines"" Problem wozu mir leider 3 Jahre fehlen um 
das dafür nötige Grundwissen für zu erlangen.

Bis jetzt läuft mein Programm soweit sehr gut, ich habe bei vielen 
Problemen meistens auch eine Lösung rausfinden können. Hier scheitere 
ich aber leider komplett.

Ich habe zwei Windows(Fenster)formen und möchte zwischen diesen beiden 
Daten austauschen.

Dies wollte ich über eine eigene Klasse machen (damit es wenigstens noch 
einigermaßen dem OOP entspricht).


Mein Problem ist, das ich es trotz Properties nicht schaffe die Werte zu 
erhalten die von der jeweils anderen Form eingetragen werden.

Ich schaffe es also nicht, das beide Formen auf exakt dieselbe Klasse 
zugreifen können und somit die Daten ausgetauscht werden können.

Meine Properties sind immer "null" sobald ich sie aus der anderen Form 
(und somit auch anderen Klasse) heraus aufrufe.
Sie werden zwar von der einen Form korrekt eingetragen, sind aber in der 
anderen Form "null" beim Abrufen.

Durch:
 CLASS meineKlasse = new CLASS() 
wird ja jeweils ein neues Objekt dieser Klasse erzeugt (eine neue 
Instanz?).

Wie schaffe ich es nun, das ich aus beiden Formen heraus den zugriff auf 
die Werte der "gemeinsamen / globalen" Klasse habe. Soweit ich das 
verstanden habe, darf es nur eine Instanz geben auf welche beide Formen 
zugreifen dürfen, damit eben auch die Inhalte untereinander "tauschbar" 
sind.

Dieses soll wie gesagt als "Datenspeicher" dienen, mit dem die 
beidenFormen komunizieren.

Hab schon rausgefunden, das es mit "singleton" gehen soll, aber was ich 
dazu finden kann ist "zu hoch" für meinen aktuellen Wissensstand, ich 
verstehe es nicht annähernd.

Hat jemand eine Idee wie man das möglichst NOOB-freundlichst lösen kann?

MFG
Marco

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erst mal was zu dem grundsätzlichen Problem des Datenaustausches:
1. Fall: Form1 erzeugt eine Form2 und stellt diese dar, dann kann Form1 
auf alle öffentlichen Methoden, Variablen, Properties etc. von Form2 
zugreifen z.B.
// in irgendeiner Methode von Form1
   Form2 form = new Form2();
   aProperty = form.aProperty;

Soll auch Form2 auf Form1 zugreifen kann man dies Form2 entweder 
mitteilen (eigene Methode, im Konstruktor), oder sie holt sich die 
Information über die Eigenschaft ParentForm (die anderen Möglichkeiten 
würden hier etwas den Rahmen sprengen)

2. Fall: Form1 und Form2 "kennen" sich nicht.
Globale Instanz einer Klasse ist z.B. eine Möglichkeit (Singleton) d.h.
die Instanz muss global sichtbar sein und es darf keine weiteren 
Instanzen geben.
In C# bzw. in der CLR z.B. Singletons oder statische Klassen
Singleton:
// erste Variante mit statischer Initialisierung
// sealed bedeutet das man von dieser Klasse keine weiteren ableiten kann,
// wodurch wiederum mehrere Instanzen möglich wären...
public sealed class Single {
    // readonly um nur die Zuweisung zuzulassen und weitere zu verhindern
    private static readonly Single instance = new Single();

    // kein öffentlicher Konstruktor
    private Single() { }

    public static Single Instance {
        get { return instance; }
    }

    public void aMethod() {
    }
}

// Multithreading-geeignete Variante
public sealed class SingleMT {
    // volatile um auch spätere Zuweisungen zuzulassen 
    private static volatile SingleMT instance;    
    private static object sync = new Object();

    // kein öffentlicher Konstruktor
    private SingleMT() { }

    public static SingleMT Instance {
        get {
            // Test ob Instanz schon erzeugt
            if (instance != null) return instance;
            // sync wird hier gelocked, damit kein weiterer Thread die
            // folgenden Befehle gleichzeitig ausführen kann 
            lock (sync) {      
                 instance = new SingleMT();
            }
            return instance;
        }
    }

    public void aMethod() {
    }
}

Bei ganz einfachen Fälle kann man aber auch eine statische Klasse 
nehmen...
static class GlobalObjects {
    public static int aPublicStaticInt = 4;
    static GlobalObjects() {      
    }
}

Stichworte für das weitere Einarbeiten wären z.B.
MVC bzw. MVP also Model-View-Controller bzw. Presenter

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

evtl. hilft dir das ein bisschen weiter:
http://www.mycsharp.de/wbb2/thread.php?threadid=488

Ralf

Autor: Marco K. (mbc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich danke euch beiden.

Die Beispiele hatte ich wohl schonmal im Netz gesehen,das Problem 
ist,das ich sie nicht annährend verstehe ... wie gesagt, mir fehlt ne 
vernünftige Ausbildung für diese ""weitergehenden"" Grundlagen.
Die Zusammenhänge der Sprache fehlen mir noch ... auch die MSDN-Seiten 
sind ein Buch mit tausend Siegeln ...

Bisher konnte ich alle Probleme irgendwie lösen, aber hier wirds wohl 
verdammt schwer werden, ich würde nämlich wenigstens gerne annähernd 
verstehen was der Code "in etwa" macht ...

Es scheint sich aber wohl leider nicht anders lösen zu lassen ... da 
werd ich wohl noch ein paar Wochen dran sitzen ...

MFG
Marco

Autor: Markus Volz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Marco,

ohne Arc Net auf die Füße treten zu wollen, aber das was er oben 
gschrieben hat, ist etwas überdimensioniert (Singleton) bzw. völlig 
überflüssig (globales Objekt). Das Problem läßt sich recht einfach 
lösen, hier ein Beispiel für die Datenklasse:
public class DataModel {
    public string stringProperty {
        ...
    }
    ...
}

Die Klasse Form1 hat einen Konstruktor, der als Parameter eine Referenz 
auf das DataModel-Objekt übergeben bekommt:
public class Form1 {
    private DataModel _dataModel;
    public Form1( DataModel dataModel ) {
        _dataModel = dataModel;
    }
    public void Foo() {
        Console.Writeln( "Test: "+_dataModel.stringProperty );
    }
}

Die Klasse Form2 ist analog aufgebaut. Alternativ zur Übergabe der 
Daten-Objekt-Referenz über den Konstruktor kann man ein 
"write-only"-Property bei den beiden Form-Klassen implementieren.

Bei der Initialisierung Deines Programms erzeugst Du jeweils eine 
Instanz von DataModel, Form1 und Form2:
public static void MyProgram( ... ) {
    ...
    DataModel myModel = new DataModel();
    Form1 myForm1 = new Form1( myModel );
    Form2 myForm2 = new Form2( myModel );
    ...
}

Hier noch die Variante mit Form-Property:
public static void MyProgram( ... ) {
    ...
    DataModel myModel = new DataModel();
    Form1 myForm1 = new Form1();
    myForm1.DataModel = myModel;
    Form2 myForm2 = new Form2();
    myForm2.DataModel = myModel;
    ...
}

Da gibt's erst mal nichts kompliziertes oder geheimnisvolles. Es geht 
allerdings etwas mehr ins Eingemachte, wenn eine Änderung in Form1 auch 
automatisch in Form2 angezeigt werden soll. Wirklich schwierig ist das 
aber auch nicht: Form1 ändert ein Property von DataModel. Bei dieser 
Änderung erzeugt DateModel ein Ereignis (Event), das von Form1 und Form2 
dahingehend verarbeitet wird, daß Form1 und Form2 sich aufgrund der 
Änderung in DataModel aktualisieren. Zu diesem Zweck registrieren sich 
beide Form-Objekte bei DataModel als Konsumenten des/der Ereignis/se. In 
C# verwendet man i.d.R. Delegates für diesen Zweck.

Ich denke, Du hast jetzt erst mal etwas zum Basteln.

Grüße
Markus

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ohne Arc Net auf die Füße treten zu wollen,

absolut nicht, hin und wieder lassen halt die Fragen etwas zu viel 
Interpretationsspielraum...

> aber das was er oben
> gschrieben hat, ist etwas überdimensioniert (Singleton) bzw. völlig
> überflüssig (globales Objekt). Das Problem läßt sich recht einfach
> lösen, hier ein Beispiel für die Datenklasse:

deswegen oben auch schon der Verweis auf MVC bzw. MVP ;-)

p.s. in der MT Variante des Singletons fehlt der zweite Test
    public static SingleMT Instance {
        get {
            if (instance != null) return instance;
            lock (sync) {      
                 if (instance == null) instance = new SingleMT();
            }
            return instance;
        }
    }

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.