GUI + Datenbank
-
Danke für die Antwort
Ich arbeite mit WinForms. An ein DataSet hab ich mich bisher nicht ran getraut, da ich gerne ein ListView verwenden möchte und zumindest in diesem Dialog keine Daten bearbeitet werden soll. Es geht um die reine Darstellung.
Der User startet also die Anwendung und erhält eine Auflistung von Artikeln. Diese sind abhängig von einer ComboBox und einem ListView, welches die Kategorie über CheckBoxes an- und abwählen lässt.
Ich habe bereits einen funktionierenden Prototyp dafür entwickelt, der aber ziemlich hässlich geworden ist... Daher suche ich nun nach einer gescheiten Lösung, da meine vermutlich nicht der richtige Weg war.
Das sah dann so aus:
ArrayList bla = DataBase.Article.RetrieveAllItems(); foreach (Item x in bla) { listView.Items.Add(x); }
Und dann kam später noch eine Suchfuntkion dazu, so das ich noch eine neue Funktion einbauen musste: Database.Articles.Filter(txtSearch.Text);
Na ja, insgesamt ziemlicher Horror, schäte ich... Bin damit sehr unzufrieden.
-
Ich war nicht untätig und habe mal ein wenig experimentiert. Hatte wohl einige Vorurteile... Tatsächlich lässt sich ein DataGridView mit einem DataTable sehr gut nutzen. Gerade deshalb, weil mein Hauptformular nur Daten darstellt. Das ist für ein DataGridView ja ein Kinderspiel und erfordert nur 2-3 Zeilen Code, wo ich vorher mühselig selber Abfragen erstellen musste.
ALlerdings bin ich noch am Experimentieren, ob ich das Aussehen eines ListView damit nachbauen kann. Mir ist das auch schon ganz gut gelungen, es sieht aber noch etwas anders aus, da nur dort GridLines angezeigt werden, wo auch ein Datensatz ist. Aber das ist eh nicht so entscheidend.
Jedenfalls ist das eine sehr nette Sache. Hätte ich nicht gedacht! Kostenlos dazu bekomme ich sogar eine Sortierung, wenn ich auf die Header drücke. Das war bei meinem Prototypen wegen des Aufwands nicht weiter in Betracht gezogen.
Jetzt muss ich nur noch schauen, wie ich die Abhängigkeiten damit verbunden bekomme. Schließlich sind die anzuzeigenden Datensätzen von der Auswahl in der Combobox abhängig. Ich muss also die Combobox mit Daten aus der Datenbank füllen (damit der User die Auswahl hat) und das DataGridView muss anhand der Auswahl die entsprechenden Datensätze anzeigen.Außerdem muss ich noch gucken, ob ich meine Eingabeformulare damit optimiert bekomme. Ich müsste nämlich z.B. noch ein Formular zum Anlegen eines neuen Artikels haben. Vielleicht kann mir dieses Konzept dabei auch helfen? Es sollte aber schon ein echtes Formular sein, da ich das Gefühl habe, das eine Eingabe direkt im Grid meinen Benutzerkreis überfordern könnte. Da ist die Verteilung auf mehrere Textfelder mit entsprechend beschreibenden Labels wohl intuitiver.
Vielen Dank schon mal für die sehr hilfreichen Tipps. Für weitere Anregungen und Vorschläge bin ich natürlich offen!
-
Wir haben auch einiges mit Datenbank-Anbindung zu tun - zwar hauptsächlich in einer anderen Sprache, aber einige Module sind auch in C# geschrieben (von einem Kollegen, der vor kurzem die Firma verlassen und mir diese Projekte übergeben hat).
Dafür haben wir eine recht konsequente Schichten-Architektur auf der Basis von Hybernate - ganz unten liegen die Daten-Objekte (prinzipiell für jede verwendete Tabelle der DB eine Klasse und eine Mapping-Definition, welche Property wie in der Datenbank abgebildet ist), darüber Manipulations-Logik (Umsetzung der elementaren SELECT/INSERT/UPDATE/DELETE-Operationen), Geschäftslogik (wie hängen die einzelnen Objekte zusammen?) und die Anwendung (kommuniziert mit dem Nutzer).
-
Hallo Kay,
schön, daß du mit dem DataGridView auf Anhieb klar gekommen bist.
Unter Vergleich DataGridView - ListView hat sich ein User die Mühe gemacht, ein DataGridView wie ein ListView aussehen zu lassen (natürlich gilt dies dann nur für den klassischen Windowsstil, nicht für Aero).Und das Beste am DataBinding ist, daß dies auch für jedes Windows-Control gilt, d.h. du kannst dir einfach ein WinForm-Formular (bzw. Dialog) erstellen (z.B. mit TextBox, ListBox, ComboBox, CheckBox, DateTimePicker etc.) und dann über die Eigenschaft 'DataBindings' deine Daten (DataSet oder DataTable etc.) daran binden, s. Control.DataBindings-Eigenschaft (dies kannst du dann auch schon direkt im Designer vornehmen!).
Ein DataBinding-Tutorial habe ich auch noch unter http://www.codeproject.com/KB/database/databinding_tutorial.aspx gefunden (scheint genau deine Anforderungen abzudecken
Und unter http://www.akadia.com/services/dotnet_databinding.html gibt es noch ein konkretes Beispiel bzgl. Master-Detail sowie eigenständigem Formular ("Example: Form's BindingContext Position Management").Viel Erfolg noch und weitere Detailfragen beantworte ich gerne...
-
Vielen Dank für die weiteren Antworten
Ich finde es ja ziemlich genial, was damit so alles möglich ist. Ich habe auch schon eine gewisse Verbindung zwischen der ComboBox und dem DataGridView hergestellt.
Das Ziel ist es, das ich in der ComboBox ein Lager auswähle. Anschließend sollen alle Artikel in diesem Lager angezeigt werden.
Programmiertechnisch scheine ich in die falsche Richtung zu denken. Bei mir werden nämlich alle Artikel angezeigt und je nachdem welchen Artikel ich anclicke verändert sich die Auswahl der ComboBox. Oder wenn ich in der ComboBox etwas auswähle, dann wird ein Artikel im DataGridView ausgewählt, der in diesem Lager ist.
Hier mal der entsprechende Code:
DataSet ds = new DataSet(); dbConnection.Open(); OleDbDataAdapter dbAdapter = new OleDbDataAdapter(new OleDbCommand("SELECT * FROM qry_Lager", dbConnection)); dbAdapter.Fill(ds, "Lager"); dbAdapter = new OleDbDataAdapter(new OleDbCommand("SELECT * FROM qry_Lagerbestand", dbConnection)); dbAdapter.Fill(ds, "Lagerbestand"); // Fill bsLager.DataSource = ds.Tables["Lager"]; bsBestand.DataSource = ds.Tables["Lagerbestand"]; dgvBestand.DataSource = bsBestand; bsLager.DataSource = bsBestand; cbLager.DataSource = bsBestand; cbLager.DisplayMember = "LagerName"; cbLager.ValueMember = "id_Lager";
Ich habe ja fast die Vermutung, das es nur einer ganz kleinen Änderung bedarf. Aber ich bin noch nicht so ganz dahinter gekommen...
-
Hallo nochmal,
'bsBestand' ist bei dir eine BindingSource, nehme ich mal an
Wenn du diese an verschiedene Controls bindest, so werden jeweils diese Controls synchronisiert (d.h. es gibt ja nur genau 1 aktuelles Item in der BindingSource)!
Entkoppel ersteinmal die ComboBox von dieser BindingSource:
cbLager.DataSource = ds.Tables["Lagerbestand"]; // bzw. kannst du auch 'bsBestand.DataSource' dafür setzen
bzw. willst du dort nicht die Lager anzeigen, also "cbLager.DataSource = bsLager" (denn bsLager benutzt du ja bisher gar nicht)!!!???
Und dann benutzt du das Combobox.SelectedIndexChanged-Ereignis (im Designer abonnieren), um die BindingSource zu filtern:
void cbLager_SelectedIndexChanged(object sender, EventArgs e) { bsBestand.Filter = "Lager = '" + (int)cbLager.SelectedItem + "'"; }
So ähnlich zumindestens.
-
Habe das so umgesetzt und funktioniert auch ganz gut, aber ich sehe da ein großes Problem:
Ich brauche ja noch 2 weitere Filter. Es sollen nur angewählte Kategorien (ListView mit Checkboxes) angezeigt werden, außerdem gibt es noch eine Suchfunktion.
Aktuell sieht es so aus (Suchfunktion bereits integriert):
// ...... bsLager.DataSource = ds.Tables["Lager"]; bsBestand.DataSource = ds.Tables["Lagerbestand"]; cbLager.DataSource = bsLager; cbLager.DisplayMember = "LagerName"; cbLager.ValueMember = "id_Lager"; dgvBestand.DataSource = bsBestand; cbLager.SelectedIndex = 0; // Activates Filter } private void cbLager_SelectedIndexChanged(object sender, EventArgs e) { if (cbLager.SelectedIndex >= 0) { bsBestand.Filter = "id_Lager = " + (cbLager.SelectedIndex + 1).ToString(); } } private void txtSuchtext_TextChanged(object sender, EventArgs e) { bsBestand.Filter = "id_Lager = " + (cbLager.SelectedIndex + 1).ToString() + " AND ArtikelName LIKE '%" + txtSuchtext.Text + "%'"; }
Ich kann in der ComboBox nun ein Lager auswählen und alle Einträge werden angezeigt. Auch kann ich die Suchfunktion einwandfrei nutzen.
Aber wenn ich jetzt noch anhand der Kategorien filtern will, dann wird es ziemlich kritisch, da ich den Filter an 3 Stellen anpassen müsste. Wenn sich die Auswahl in der ComboBox ändert, wenn sich der Suchtext ändert, und wenn ein Element in der ListView an- bzw. abgewählt wird. Alternativ kann ich eine Funktion ApplyFilter bauen, die ich an diesen 3 Stellen aufrufe. Ist das denn das korrekte Vorgehen? Ich hatte diese Lösung bisher abgelehnt, da ich dachte, das ich mit den BindingSource einfach alles so binde, dass diese Funktionalitäten ohne mein weiteres zutun funktionieren.
-
Ahh, da ist schon der erste Bug. Der Filter in cbLager_SelectedIndexChanged muss natürlich auch den Suchtext berücksichtigen. Ansonsten wird die Eingabe nach der Auswahl eines anderen Lagers ignoriert.
-
Hallo,
wenn du verschiedene Filter kombinieren willst, dann bleibt dir nichts anderes übrig, als (wie schon von dir erwähnt) dafür eine eigene Methode zu schreiben.
Das System kann ja nicht automatisch die verschiedenen Filterkriterien kennen (z.B. AND, OR, LIKE etc.)Du kannst aber auch mal bei CodeProject schauen, ob es nicht schon fertige DGV mit Filter- (und Sortier-) Funktionalität gibt.
Auf die Schnelle habe ich folgende gefunden (ohne sie mir näher angesehen zu haben):
http://www.codeproject.com/KB/grid/gridextensions.aspx
http://www.codeproject.com/KB/miscctrl/Datagridview_Fiter.aspx
http://www.codeproject.com/KB/grid/SQLDatagridview.aspx
http://www.codeproject.com/KB/grid/DataGridViewFilterUC.aspx
http://www.codeproject.com/KB/database/filterdialog.aspxIm professionellen Bereich werden auch sehr oft die Komponenten von
DevExpress: XtraGrid
bzw.
Infragistics: WinGrid
eingesetzt (daß du mal siehst, was sonst noch alles möglich ist
-
Vielen Dank dafür
Ich denke, das ich das nun gut gelöst bekomme.