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


von Marco K. (mbc)


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:
1
 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

von Arc N. (arc)


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.
1
// in irgendeiner Methode von Form1
2
   Form2 form = new Form2();
3
   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:
1
// erste Variante mit statischer Initialisierung
2
// sealed bedeutet das man von dieser Klasse keine weiteren ableiten kann,
3
// wodurch wiederum mehrere Instanzen möglich wären...
4
public sealed class Single {
5
    // readonly um nur die Zuweisung zuzulassen und weitere zu verhindern
6
    private static readonly Single instance = new Single();
7
8
    // kein öffentlicher Konstruktor
9
    private Single() { }
10
11
    public static Single Instance {
12
        get { return instance; }
13
    }
14
15
    public void aMethod() {
16
    }
17
}
18
19
// Multithreading-geeignete Variante
20
public sealed class SingleMT {
21
    // volatile um auch spätere Zuweisungen zuzulassen 
22
    private static volatile SingleMT instance;    
23
    private static object sync = new Object();
24
25
    // kein öffentlicher Konstruktor
26
    private SingleMT() { }
27
28
    public static SingleMT Instance {
29
        get {
30
            // Test ob Instanz schon erzeugt
31
            if (instance != null) return instance;
32
            // sync wird hier gelocked, damit kein weiterer Thread die
33
            // folgenden Befehle gleichzeitig ausführen kann 
34
            lock (sync) {      
35
                 instance = new SingleMT();
36
            }
37
            return instance;
38
        }
39
    }
40
41
    public void aMethod() {
42
    }
43
}

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

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

von Ralf (Gast)


Lesenswert?

Hi,

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

Ralf

von Marco K. (mbc)


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

von Markus Volz (Gast)


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:
1
public class DataModel {
2
    public string stringProperty {
3
        ...
4
    }
5
    ...
6
}

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

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:
1
public static void MyProgram( ... ) {
2
    ...
3
    DataModel myModel = new DataModel();
4
    Form1 myForm1 = new Form1( myModel );
5
    Form2 myForm2 = new Form2( myModel );
6
    ...
7
}

Hier noch die Variante mit Form-Property:
1
public static void MyProgram( ... ) {
2
    ...
3
    DataModel myModel = new DataModel();
4
    Form1 myForm1 = new Form1();
5
    myForm1.DataModel = myModel;
6
    Form2 myForm2 = new Form2();
7
    myForm2.DataModel = myModel;
8
    ...
9
}

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

von Arc N. (arc)


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
1
    public static SingleMT Instance {
2
        get {
3
            if (instance != null) return instance;
4
            lock (sync) {      
5
                 if (instance == null) instance = new SingleMT();
6
            }
7
            return instance;
8
        }
9
    }

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.