Autor Beitrag
alegria
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 79



BeitragVerfasst: Mi 22.10.08 18:56 
Hallo allerseits!

Also erstmal vorneweg: ich bin absoluter Anfänger und entsprechend auch nicht so fit in der Fachsprache Ich hoffe man kann mir das nachsehen und Ihr versteht trotzdem mein Problem...

Nun ich habe zwei WindowForms (Form1 und Form2) wo jeweils zwei DataGridViews(DGV1 und DGV2) mit diversen Daten gefüllt sind. Es gibt auch eine Methode "Verarbeitung" welche als public in Form1 liegt. Diese hat eine Variable "current_DGV" welche in Abhängigkeit von wo die Methode aufgerufen wird, entweder DGV1 (aus Form1) oder DGV2 (aus Form2) der Variable zuordnen soll. Von wo aufgerufen wird, würde ich über die "activeform" eigenschaft regulieren. Dummerweise kann ich aber der Variable current_DGV nie Form2.DGV2 zuordnen. Und wenn ich mit
Form2 irgendwas = new Form2();
ein neues Objekt anlege, kann ich zwar scheinbar mit
irgendwas.DGV2
auf DGV2 zugreifen, aber das ist logischerweise leer, da ich ja Form2 NEU ("new") instanziere und demnach auch nicht auf mein eigentliches Form2.DGV2 zugreife...

Hat jemand ne Idee wie ich sowas lösen kann???

Vielen Dank im Voraus...

P.S. Achso: eine Übergabe des DataGridViews an die Methode scheidet aus, da ich von so vielen Stellen aus drauf zugreife, dass es ziemlich aufwendig ist ständig das mitzugeben... Denke der Weg wie oben beschrieben (rausfinden was activeform ist und dementsprechend die DGVs zuordnen) ist der bessere...
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4807
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Do 23.10.08 09:39 
Also, dein Weg ist nicht so toll...

So hast du Abhängigkeiten zwischen den Formularen, die nicht sein sollten.
Es gibt weitaus bessere Wege:
1. Erzeugen einer Basisklasse für beide Formulare, in denen du dann die Methode (+ evtl. schon das DGV etc.) implementierst und jede Form-Klasse greift dann nur noch auf sein DGV zu.
2. Erzeugen einer externen Klasse, in der du die Methode auslagerst (diese Klasse entweder als Singleton oder aber mittels statischer Methode implementieren)
3. ...

Je nachdem, ob deine "Verarbeitung"-Methode nur reine GUI-Aufgaben oder aber auch Logik beinhaltet, solltest du evtl. eine eigene Logik-Klasse erzeugen.
Die Trennung von GUI und Logik (und evtl. noch Datenzugriff) ist elementar für jedes gute Programm!

Positiv ist aber anzumerken, daß du die Funktionalität nur an einer Codestelle haben willst, anstatt die Methode zu duplizieren.
alegria Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 79



BeitragVerfasst: Fr 24.10.08 21:02 
Puh! Harter Tobakkk!!! Also ich hab zwar versucht zu verstehen was Du meinst, aber richtig schlau draus geworden bin ich leider nicht... Für mich klingt das nicht schlüssig weil ich halt nicht weiss wie ich bspw. Nr 1 praktisch umsetzen soll!?

Ich geb mal bissl Code - vielleicht ist das leichter wenn man der theoretischen abstraktionsebene etwas praktisches beimischt...

:: 1. meine besagt Methode die sich momentan noch innerhalb von Form 1 befindet ::

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
public void myMethod(int variante)
        {
            DataGridView current_dgv;
            if (ActiveForm.Name.ToString() == "Form1")
            {
                current_dgv = dgv_Form1;
            }
            else
            {
                // HIER LIEGT PROBLEM - NEW macht halt NEW und nicht bestehendes....
                Form2 frmForm2 = new Form2();
                current_dgv = frmForm2.dgv_Form2;
            }

                If (variante == 1) {
                        current_dgv... etc.usw.usf. //hier dann der allgemeine Teil - der "logische"...
                ...
        }


:: im FORM1 ruft ich dann die Methode so auf... ::

...
ausblenden C#-Quelltext
1:
myMethod(1);					

...

:: und in FORM2 (was wohl so vom Aufruf her richtig ist?) ::

ausblenden C#-Quelltext
1:
2:
Form1 frmForm1 = new Form1();
frmForm1.myMethod(1);


Wär nett wenn Ihr mir weiterhelfen könntet... Das ist für mich wirklich eine wichtige Sache und würde mich um einiges voranbringen... Dennn wer will schon Redundanzen im Code! ;)

P.S. integer Variante kann man getrost ignorieren... Es regelt lediglich Varianten die für jedes dgv möglich sind...
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Sa 25.10.08 11:47 
user profile iconalegria hat folgendes geschrieben Zum zitierten Posting springen:
Puh! Harter Tobakkk!!! Also ich hab zwar versucht zu verstehen was Du meinst, aber richtig schlau draus geworden bin ich leider nicht... Für mich klingt das nicht schlüssig weil ich halt nicht weiss wie ich bspw. Nr 1 praktisch umsetzen soll!?

Grundstruktur sollte etwas sein wie dieses:
ausblenden C#-Quelltext
1:
2:
3:
public class BaseForm : Form { ... }
public class Form1 : BaseForm { ... }
public class Form2 : BaseForm { ... }

In BaseForm (!) wäre ein DataGridView und MyMethod enthalten, vermutlich jeweils als protected deklariert. In Form1 und Form2 steuerst Du, soweit erforderlich, die jeweilige DataSource. Dann kannst Du in jedem der abgeleiteten Formulare direkt MyMethod aufrufen und bist sicher, dass das jeweils aktive DGV benutzt wird.

Inwieweit das sinnvoll ist, möchte ich wirklich bezweifeln. Denn die Maßnahmen, die Du dort skizziert hast, beziehen sich wohl auf die tatsächlich benutzten Daten; und dann wird das wird unübersichtlich oder inkonsistent. Deshalb dürfte Th69's 2. Variante besser sein.

user profile iconalegria hat folgendes geschrieben Zum zitierten Posting springen:
Ich geb mal bissl Code - vielleicht ist das leichter wenn man der theoretischen abstraktionsebene etwas praktisches beimischt...

Danke, aber das Problem hatte ich schon bei der ersten Beschreibung verstanden.

user profile iconalegria hat folgendes geschrieben Zum zitierten Posting springen:
// HIER LIEGT PROBLEM - NEW macht halt NEW und nicht bestehendes....

Eben: Du musst das bestehende Formular holen. Mit ActiveForm geht es etwa so:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
DataGridView current_dgv;
if (ActiveForm == this)
    current_dgv = this.dgv_Form1;
else if (ActiveForm is Form2)
    current_dgv = (ActiveForm as Form2).dgv_Form2;
else if // usw.

Aber beachte, dass die DGVs entsprechend als internal deklariert werden müssen, damit sie zur Verfügung gestellt werden können. Auch hier gilt wieder: es wird unübersichtlich.

Mit OpenForms könntest Du es so lösen, aber dann sollten alle DGVs gleich heißen und müssten ebenfalls als internal deklariert werden:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
DataGridView current_dgv = null;
foreach(Form frm in Application.OpenForms) {
   if (frm is ActiveForm) {
      Control[] items = frm.Controls.Find("DGV"true);
      if (items.Count == 1) {
         current_dgv = items[0as DataGridView;
         break;
      }
   }
}


user profile iconalegria hat folgendes geschrieben Zum zitierten Posting springen:
:: und in FORM2 (was wohl so vom Aufruf her richtig ist?) ::
ausblenden C#-Quelltext
1:
2:
Form1 frmForm1 = new Form1();
frmForm1.myMethod(1);

Nein, das ist ziemlich abwegig: Zum einen wird ein neues Form1 erzeugt und nicht das vorhandene benutzt; dann benutzt Du diese Instanz nur wegen dieser Methode; die "gemeinsame" Methode steht irgendwo, aber nicht dort, wo sie benötigt wird.

Ich kann also auch nur betonen:
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
Also, dein Weg ist nicht so toll... So hast du Abhängigkeiten zwischen den Formularen, die nicht sein sollten.

Je nachdem, ob deine "Verarbeitung"-Methode nur reine GUI-Aufgaben oder aber auch Logik beinhaltet, solltest du evtl. eine eigene Logik-Klasse erzeugen.
Die Trennung von GUI und Logik (und evtl. noch Datenzugriff) ist elementar für jedes gute Programm!

Vielleicht solltest Du beschreiben, was Du in myMethod eigentlich erledigen willst. Dann können wir konkrete Vorschläge machen. Jürgen
alegria Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 79



BeitragVerfasst: So 26.10.08 11:50 
Also erstmal einen Riesendank für die schnelle, konkrete und effektive Antwort!

Das mit dem abgeleiteten Formularen klappt super. Genau was ich gesucht habe! :)

Warum das jetzt nicht so super sein soll versteh ich nicht so richtig...
Zitat:
Denn die Maßnahmen, die Du dort skizziert hast, beziehen sich wohl auf die tatsächlich benutzten Daten; und dann wird das wird unübersichtlich oder inkonsistent. Deshalb dürfte Th69's 2. Variante besser sein.

Zu den skizzierten Massnahmen... Ich will ne Tabellenauf-/bearbeitung in der Methode (nun ja auch Klasse) machen. Also so Kram wie Excelexport, Drucken, CSV-Download etc. Und genau deshalb will ich ja von jeder Form (oder allgemeiner von überall dort wo datagridviews sind...) darauf zugreifen...
Zu Th69's 2 Variante... Naja... Unter "externer Klasse" kann ich mir ja noch was vorstellen... Aber wie ich die Klasse dann "entweder als Singleton oder aber mittels statischer Methode implementieren" kann ist mir schleierhaft. Ehrlich gesagt weiss ich auch nciht so richtig ob das für meinen Anwendungsfall so richtig nötig/sinnvoll ist!?

Aber wie gesagt nochmals danke es funktioniert ja jetzt erstmal...
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: So 26.10.08 12:55 
Danke für die Erläuterungen; sie bestätigt Th69's und meine Bedenken: Du willst die Daten bearbeiten; das ist von der GUI möglichst zu trennen.

Auch wenn Du es jetzt gelöst hast, solltest Du schnellstmöglich auf ein besseres Verfahren umsteigen: Erstelle eine separate Klasse, die alles enthält, was mit den Daten gemacht wird: Einlesen, Ändern, Speichern, Export, ggf. auch Drucken (für den Druck passt vielleicht noch eine weitere Klasse, falls auch noch andere Daten auf gleiche oder ähnliche Weise gedruckt werden sollen). Diese Klasse könnte abgeleitet sein von DataTable.

Diese Klasse wird entweder als singleton erzeugt, damit sie von jedem Formular aus aufgerufen werden kann und immer dieselbe Instanz zur Verfügung steht; oder eine Instanz wird vom Hauptformular aus erzeugt und eine Referenz darauf an die anderen Formulare übergeben. Jedes DataGridView bekommt als DataSource diese Referenz - fertig. In den Formularen machst Du Dir keine Gedanken mehr über die Daten.

Beispiele für singleton findest Du in der Forumssuche, in Google und sogar unter Wikipedia.

Jürgen
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4807
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 27.10.08 12:05 
Hallo alegria,

ich weiß, daß man als Anfänger erst mal nur "Bahnhof" versteht, aber ich möchte mit meinen Vorschlägen dir nur helfen, daß du nicht erst ein Riesendurcheinander in deinem Code erzeugst, so daß das Programm nachher nicht mehr wartbar ist.
Und da du ja geschrieben hast, daß sich die Verarbeitung nur auf die Daten bezieht, so sollten diese Daten (und deren Methoden) völlig unabhängig von der GUI (DataGridView) in einer eigenen Klasse stehen (sogar in einer anderen Source-Datei).

Und danke auch an JüTho für deine Unterstützung.