Entwickler-Ecke
WinForms - Form1 BindingSource in Form2 Combobox verwenden?
avoid - So 12.04.20 15:54
Titel: Form1 BindingSource in Form2 Combobox verwenden?
ich habe in meinem ersten Form ein dataset und eine bindingsource und DataGridView das diese bindingsource verwendet.
Das DataGridView hat ein par Spalten die als Combobox aus anderen Tabellen befüllt sind.
in meinem Form2 gibt es eine Combobox die ich nun aus der Bindingsource füllen möchte.
wenn ich mir nun die Eigenschaften dieser Combobox an sehe gibt es hier ein DataSource und ein DataMember.
Leider hab ich in Form2 keine quellen zur Auswahl, obwohl ich diese im ersten Form schon auf public gestellt hab.
wie ich eine einfache variable mit get und set hin und her reichen kann, das bekomme ich hin.
aber wie übergebe ich eine BindingSource an ein zweites Formular?
aus diesem Beitrag konnte ich schon etwas wissen mit nehmen aber schlau werde ich daraus nicht.
https://entwickler-ecke.de/viewtopic.php?t=105488&highlight=public+dataset+dataset+get+set
ich hoffe jemand kann mir einen Hinweis geben.
Moderiert von Th69: Titel geändert ("Frage:" entfernt.)
Ralf Jansen - So 12.04.20 18:00
Du solltest eine BindingSource nicht rumreichen die ist selbst eine Winforms Komponente und gehört zu einer Form oder sonstigem ContainerControl. Eine andere Form sollte eine eigene BindingSource haben der du dann deine Datenquelle zuweist.
Zitat: |
Leider hab ich in Form2 keine quellen zur Auswahl, obwohl ich diese im ersten Form schon auf public gestellt hab. |
Das kann so nicht funktionieren. Von deinen Formen kann es zur Laufzeit beliebig viele Instanzen geben. Welcher Form2 sollte den von welcher Form1 was übergeben oder geholt werden wenn es von beiden z.B. dutzende gleichzeitig gibt?
Das ist während dem designen nicht lösbar und du musst schon zur Laufzeit eine passende Zuweisung machen.
avoid - Mo 13.04.20 06:12
Ich glaube wir reden aneinander vorbei.
Im ersten Form habe ich mein dataset mit bindingsource, gridview und noch ein par andere Sachen.
Nun habe ich Form2, mit diversen TextBoxen und einer Combobox, als Eingabemaske erstellt.
Du kannst mir nicht erzählen das sich die im ersten Form verwendeten Komponenten nicht von Form2 aus verwenden lassen.
Das würde ja jede Art von Dialogfenstern verhindern.
Wenn ich die Combobox im selben Form habe, kann ich bei deren Eigenschaften problemlos DataSource und ein DataMember auswählen.
Wenn ich nur die Werte einer Variablen übergeben will geht das doch auch per Member-Variable (get und set).
Mal davon abgesehen das der Beitrag von Th68, den ich verlinkt habe, zeigt das es sogar mit einem Dataset geht.
Ich möchte nur wissen wie das für ein Bindingsource funktioniert.
Ich mach doch keine Kopie vom kompletten Dataset für Form2, wenn ich nur den Inhalt einer spalte aus einer Tabelle brauche.
Das würde die Effizienz von Objektorientierung doch obsolet machen oder nicht?
Th69 - Mo 13.04.20 08:55
So wie Ralf schon geschrieben hat, solltest du eine BindingSource nicht weiterreichen, d.h. für verschiedene Komponenten unterschiedlicher Forms verwenden (denn diese speichert den aktuellen Datensatz, so daß eine Auswahl in einer Form automatisch auch die Auswahl in der anderen Form durchführen würde), jedoch kannst du das DataSet (als Referenz) weiterreichen und jeweils an eine eigene BindingSource binden.
Ralf Jansen - Mo 13.04.20 12:18
Zitat: |
Ich mach doch keine Kopie vom kompletten Dataset für Form2, wenn ich nur den Inhalt einer spalte aus einer Tabelle brauche.
Das würde die Effizienz von Objektorientierung doch obsolet machen oder nicht? |
Da du auch den verlinkten Beitrag nochmal ansprichst. Dir ist klar das das dort gezeigte Zuweisen des Datasets eben keine Kopie ist?
Wenn nicht, solltest du dir den Unterschied zwischen Referenz- und Wertetypen nochmal verdeutlichen.
Es ist völlig normal die Daten den Formen von außen zuzuweisen. Und es ist auch normal das als Referenzen zutun und die Daten mehreren Formen zuzuweisen. Kopien von Daten macht man eigentlich nur auf Datensatzebene wenn man ein sauberes Undo Verhalten beim Ändern von Daten braucht und die Klassen die man als Datenquelle nutzt das nicht irgendwie schon mitbringen (und DataRows bringen das mit). An dieser Stelle hilft die BindingSource beim Zuweisen zu einer Form-Instanz. Man braucht nur eine Zuweisung zur BindingSource und muss nicht alle Controls der Form durchrennen sondern kann diese Verbindung BindingSource<->Controls schon im Designer machen. Es gibt also auch keine Vorteil nicht einfach für jede Form eine eigene Bindingsource zu benutzen. Unbeachtet dessen das Winforms so nicht funktioniert. Eine Komponente ist an die Lebenszeit gekoppelt zur Form zu der sie gehört. Würdest du sie darüber hinaus irgendwo verwendest hast du ganz schnell das Problem das sie schon zerstört ist während du sie woanders noch benutzen möchtest.
avoid - Mo 13.04.20 12:39
Th69 hat folgendes geschrieben : |
denn diese speichert den aktuellen Datensatz, so daß eine Auswahl in einer Form automatisch auch die Auswahl in der anderen Form durchführen würde |
Ich kann das noch immer nicht nachvollziehen, wohl weil ich den Funktionsumfang und die Komplexität einer
BindingSource nicht kenne.
Könnt ihr mir evtl. ein Fallbeispiel geben damit ich es raffe?
Ich sehe es nicht als Problem wenn das
DataGridView in Form1 Zeilen markiert weil ich in einer
ComboBox einen anderen Eintrag auswähle.
Davon geht doch nix kaputt, die Selektion kann ich doch beim schließen von Form2 mit
.ClearSelection(); und
.CurrentCell = null; entfernen.
@Rald Jansen
Verstehe, ist also nur eine Referenz auf das Dataset. Ja da tue ich mir noch sehr schwer. Vermutlich weil mir Abstraktes denken nicht so liegt.
Jetzt wo du auf die Lebenszeit der Komponente hin weist ist mir das auch schon etwas klarer geworden, warum ihr beiden so allergisch darauf reagiert das ich die
BindingSource weiterreichen wollte.
Also doch das
DataSet.
Oder dem Form2 eine aufbereitete
ItemList mit geben?
Th69 - Mo 13.04.20 13:48
Der Anwender wählt in
Form1 einen Datensatz aus, dann wird ein zweites
Form2 geöffnet (und dieselbe
BindingSource würde dann dort benutzt), und dann wählt der Anwender dort einen anderen Datensatz aus, so würde dann automatisch auch in
Form1 dieser Datensatz ausgewählt sein (analog würde bei
CurrentCell = null dann auch die Auswahl in
Form1 gelöscht werden) - also ich kenne keinen Anwender, welcher das so haben möchte (und auch kein Programm, da sich so verhält).
Und nicht jede
Form/UserControl/Komponente benötigt überhaupt für die Datenbinding eine
BindingSource. Diese wird ja hauptsächlich in Verbindung mit einem
BindingNavigator [
https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.bindingnavigator] benutzt, so daß andere Komponenten Details zu dem Datensatz anzeigen können (z.B. Name, Vorname, Adresse, ...). Wenn man nur eine Liste (in einem Dialog) anzeigen möchte, so braucht man dafür dann nicht extra eine
BindingSource, sondern kann direkt diese Liste (bzw.
DataSet oder
DataTable) binden (so verstehe ich zumindestens deine erwähnte
ComboBox auf
Form2).
Und "Abstraktes Denken" bedeutet nicht zwangsläufig rein theroretisches Denken - alleine schon die Anwendung von Datenkapselung und Wiederverwertbarkeit gehören schon dazu (und sind eben ein Teil des Software-Engineerings).
avoid - Mi 15.04.20 13:46
Ich hab es jetzt wie folgt gelöst.
Im mainForm verwende ich diese Zeilen um mein zweites Form auf zu rufen und das
dataSet1 dort hin zu übergeben.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| private void dataset_entry_Add(object sender, EventArgs e) { FormAddEditDialog addEditdialog = new FormAddEditDialog(); addEditdialog.DataSetBuffer = this.dataSet1; addEditdialog.fillFromDataSet(); DialogResult dRresult = addEditdialog.ShowDialog(); } |
Im zweiten Form habe ich dann folgenden Code hinzugefügt und soweit funktioniert es schon mal.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| public DataSet DataSetBuffer { get; set; } public void fillFromDataSet() { bauformbindingSource.DataSource = DataSetBuffer ; bauformbindingSource.DataMember = "Bauform"; comboBox_bauform.DataSource = bauformbindingSource; comboBox_bauform.DisplayMember = "Column_Bauform"; herstellerbindingSource.DataSource = DataSetBuffer ; herstellerbindingSource.DataMember = "Hersteller"; comboBox_hersteller.DataSource = herstellerbindingSource; comboBox_hersteller.DisplayMember = "Column_Herstellername"; lieferantbindingSource.DataSource = DataSetBuffer ; lieferantbindingSource.DataMember = "Lieferant"; comboBox_lieferant.DataSource = lieferantbindingSource; comboBox_lieferant.DisplayMember = "Column_Lieferantname"; bauteileBindingSource.DataSource = DataSetBuffer ; bauteileBindingSource.DataMember = "Bauteile"; } |
Habt ihr es so gemeint?
Th69 - Mi 15.04.20 16:49
Ja, so.
Jedoch würde ich die fillFromDataSet()-Methode privat machen, so daß diese automatisch im Setter von DataSetBuffer aufgerufen wird. Oder aber, du übergibst das DataSet im Konstruktor.
Ralf Jansen - Mi 15.04.20 19:33
Zitat: |
Habt ihr es so gemeint? |
Im Prinzip ja.
Was ich hier jetzt nicht verstehe ist warum du für jedes Control eine eigene BindingSource hast?
Eigentlich ist, in meiner Vorstellung, der Sinn der BindingSource davon nur eine(im einfachen normalen Fall) zu haben. Dann im Designer die Beziehung zwischen dieser einen Bindingsource und allen Controls die per Databinding angesprochen werden herzustellen und im Code verkommt das dann zu einem Einzeiler.
fillFromDataSet würde bei mir dann eigentlich nur das enthalten
meineLiebeBindingSource.DatsSource = DataSetBuffer.
Ich hätte davon dann auch keine extra Methode gemacht sondern eine Überladung von ShowModal erzeugt der man das Dataset mitgeben kann und diesen Einzeiler enthält. Den Return von ShowModal (DialogResult) kann man dann im Aufrufer schön benutzen um eventuell Dinge zu tun die nun notwendig sind je nachdem ob sich der User in deinem Bearbeitungsdialog dazu entschlossen hat seine Änderungen zu übernehmen oder diesen Dialog abgebrochen hat.
Th69 - Do 16.04.20 07:55
@Ralf, das DataSet besteht ja aus einzelnen Tabellen, welche dann je nach Control zugewiesen werden (m.E. gibt es keine Möglichkeit bei einem DataSet als BindingSource für ein einzelnes Control dann Tabelle und anzuzeigende Spalte anzugeben). Alternativ könnte man jeweils eine
DataView [
https://docs.microsoft.com/de-de/dotnet/api/system.data.dataview] dazwischenschalten, aber die 2 Schichten (
DataSet ->
DataTable) müssen getrennt verwaltet werden.
avoid - Do 16.04.20 13:24
Es sind vier Tabellen im
DataSet, darum hab ich für jede ein
BindingSource erstellen müssen.
@Ralf Jansen,
ginge es nur um eine Tabelle gebe ich dir vollkommen recht, dann hätte ein
BindingSource genügt.
Wobei, hätte ich dann nicht wieder das Problem mit der Auswahl? Ändere ich die in einer
Combobox springt sie in den anderen mit?
aber ja, ich hab ja oben von einer
Combobox gesprochen.
@Th69,
ich hab es gerade mal versucht aber er erwartet dann bei
get auch etwas.
C#-Quelltext
1:
| public DataSet DataSetBuffer { get; set => fillFromDataSet(); } |
Ich finde leider kein Syntaxbeispiel das mir zeit wie das richtig geht.
Th69 - Do 16.04.20 13:36
Sobald man den Getter oder Setter selbst implementiert, benötigt man ein eigenes sog. "backing field" (d.h. eine private Membervariable):
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| private DataSet _dataset;
public DataSet DataSetBuffer { get { return _dataset; } set { _dataset = value; fillFromDataSet(); } } |
avoid - Do 16.04.20 15:43
das war mir klar, dachte nur das kann man irgendwie vermeiden.
aber return alleine wollte er nicht fressen weil er ja nicht wusste was er zurück geben soll.
dann mach ich das so wie du es geschrieben hast.
danke.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!