Gegeben ein Datenmodell für Bestell-Vorgänge:
Es gibt Artikel, Bestellungen und BestellPosten. Bestellposten ist Mittler-Tabelle der m:n - Relation zw. den beiden erstgenannten.
Praktisch bedeutet das, dass in einer Bestellung mehrere Bestellposten enthalten sind, und jeder Bestellposten verweist auf einen Artikel, und gibt die Anzahl an, wieviele dieser Artikel bestellt sind.
Besonderheit: zusammengesetzter Primärschlüssel
Bestellpostens Primärschlüssel ist hier interessanterweise keine eigene Tabellenspalte, sondern setzt sich zusammen aus den beiden ForeignKeys zu Artikel und Bestellung.
Bekanntlich (hoffentlich) muß so ein Primärschlüssel ja eindeutig sein, und bei zusammengesetzten PrimKeys bedeutet das, dass die Kombination beider Fremdschlüssel einzigartig sein muß.
Praktisch bedeutet das, dass in einer Bestellung derselbe Artikel nicht in 2 verschiedenen Posten auftauchen kann, und das ist hier genau die beabsichtigte Einschränkung.
Dieses Datenmodell soll verhindern, dass man in einer Bestellung 3 Cola, 1 Fanta und nochmal 1 Cola bestellen kann.
Stattdessen, wenn der User während des Bestellens merkt, dass 3 Cola zuwenig sind, ist er gezwungen, die Anzahl des bestehenden Cola-BestellPostens einfach erhöhen, statt einen weiteren Cola-BestellPosten hinzuzufügen.
Useability-Problem im Gui
Angenommen, man hat eine Bestellung in Ansicht, will einen Posten hinzufügen, und öffnet die entsprechende Combobox zur Auswahl des Artikels. Von Natur aus weiß diese Combo ja nix davon, dass ein Artikel nicht erneut angewählt werden darf, wenn er in dieser Bestellung bereits vorkommt.
Ein cooles Gui ist also bestrebt, die unerlaubten Artikel aus der Combo zu entfernen, bevor sie geöffnet wird.
Jo, das habe ich hier mal gemacht. Als Combo habe ich die Combo einer DataGridViewComboboxColumn, und der Zugriff erfolgt im EditingControlShowing - Event des DatagridViews.
Das ist ein bischen ein Hack, weil normalerweise ist für die EditingCombo das Databinding eingerichtet entsprechend den im Designer getätigten Einstellungen der DataGridViewComboboxColumn.
Jetzt aber wird das Databinding aufgelöst, und stattdessen werden die Items der ItemCollection geadded - also aus der gebundenen Combo wird eine ungebundene gemacht.
Dasselbe nochmal mit Linq ;o)
Zulässige Anzahl Bestellposten beschränken
Ein weiteres (kleineres) Problem ist, dass bei diesem Datenmodell natürlich keinesfalls mehr Bestellposten einer Bestellung zugefügt werden können, als es Artikel gibt - denn sonst wäre ja einer doppelt aufgeführt.
Jo, genau diese Aussage kann man im ListChanged-Event der entsprechenden BindingSource quasi in Code gießen, und hat das Problem damit gelöst:
Es gibt Artikel, Bestellungen und BestellPosten. Bestellposten ist Mittler-Tabelle der m:n - Relation zw. den beiden erstgenannten.
Praktisch bedeutet das, dass in einer Bestellung mehrere Bestellposten enthalten sind, und jeder Bestellposten verweist auf einen Artikel, und gibt die Anzahl an, wieviele dieser Artikel bestellt sind.
Besonderheit: zusammengesetzter Primärschlüssel
Bestellpostens Primärschlüssel ist hier interessanterweise keine eigene Tabellenspalte, sondern setzt sich zusammen aus den beiden ForeignKeys zu Artikel und Bestellung.
Bekanntlich (hoffentlich) muß so ein Primärschlüssel ja eindeutig sein, und bei zusammengesetzten PrimKeys bedeutet das, dass die Kombination beider Fremdschlüssel einzigartig sein muß.
Praktisch bedeutet das, dass in einer Bestellung derselbe Artikel nicht in 2 verschiedenen Posten auftauchen kann, und das ist hier genau die beabsichtigte Einschränkung.
Dieses Datenmodell soll verhindern, dass man in einer Bestellung 3 Cola, 1 Fanta und nochmal 1 Cola bestellen kann.
Stattdessen, wenn der User während des Bestellens merkt, dass 3 Cola zuwenig sind, ist er gezwungen, die Anzahl des bestehenden Cola-BestellPostens einfach erhöhen, statt einen weiteren Cola-BestellPosten hinzuzufügen.
Useability-Problem im Gui
Angenommen, man hat eine Bestellung in Ansicht, will einen Posten hinzufügen, und öffnet die entsprechende Combobox zur Auswahl des Artikels. Von Natur aus weiß diese Combo ja nix davon, dass ein Artikel nicht erneut angewählt werden darf, wenn er in dieser Bestellung bereits vorkommt.
Ein cooles Gui ist also bestrebt, die unerlaubten Artikel aus der Combo zu entfernen, bevor sie geöffnet wird.
Jo, das habe ich hier mal gemacht. Als Combo habe ich die Combo einer DataGridViewComboboxColumn, und der Zugriff erfolgt im EditingControlShowing - Event des DatagridViews.
VB.NET-Quellcode
- Private Sub PostenDataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles PostenDataGridView.EditingControlShowing
- If PostenDataGridView.CurrentCell.ColumnIndex <> clmPostenArtikelID.DisplayIndex Then Return 'abbrechen, wenn das EditingControl einer anderen Spalte angehört
- Dim cmb = DirectCast(e.Control, ComboBox)
- Dim src = ReduceComboColumnDts.Artikel.ToList 'alle Artikel
- Dim selItem As ArtikelRow = Nothing
- With PostenBindingSource
- For i = 0 To .Count - 1
- 'diejenigen Artikel rauswerfen, auf die bereits durch andere PostenRows verwiesen wird
- Dim art = .At(Of PostenRow)(i).ArtikelRow
- If i = .Position Then
- selItem = art 'SelectedItem merken
- Else
- src.Remove(art)
- End If
- Next
- End With
- Dim bnds = {cmb.DisplayMember, cmb.ValueMember} 'Member-Einstellungen merken
- cmb.DataSource = Nothing 'bisheriges Databinding auflösen
- cmb.Items.AddRange(src.ToArray) 'statt binden Items adden
- 'Member-Einstellungen restaurieren
- cmb.DisplayMember = bnds(0)
- cmb.ValueMember = bnds(1)
- cmb.SelectedItem = selItem
- End Sub
Jetzt aber wird das Databinding aufgelöst, und stattdessen werden die Items der ItemCollection geadded - also aus der gebundenen Combo wird eine ungebundene gemacht.
VB.NET-Quellcode
- Private Sub PostenDataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles PostenDataGridView.EditingControlShowing
- If PostenDataGridView.CurrentCell.ColumnIndex <> clmPostenArtikelID.DisplayIndex Then Return 'abbrechen, wenn das EditingControl einer anderen Spalte angehört
- Dim currPosten = PostenBindingSource.At(Of PostenRow)()
- Dim toExcept = From x In PostenBindingSource.All(Of PostenRow)() Where x IsNot currPosten Select x.ArtikelRow
- Dim comboSource = srcClmArtikelId.All(Of ArtikelRow).Except(toExcept)
- With DirectCast(e.Control, ComboBox)
- Dim memberSettings = {.DisplayMember, .ValueMember} 'Member-Einstellungen merken
- .DataSource = Nothing 'bisheriges Databinding auflösen
- .Items.AddRange(comboSource.ToArray) 'statt Databinding Items adden
- 'Member-Einstellungen restaurieren
- .DisplayMember = memberSettings(0)
- .ValueMember = memberSettings(1)
- .SelectedItem = currPosten.ArtikelRow
- End With
- End Sub
Zulässige Anzahl Bestellposten beschränken
Ein weiteres (kleineres) Problem ist, dass bei diesem Datenmodell natürlich keinesfalls mehr Bestellposten einer Bestellung zugefügt werden können, als es Artikel gibt - denn sonst wäre ja einer doppelt aufgeführt.
Jo, genau diese Aussage kann man im ListChanged-Event der entsprechenden BindingSource quasi in Code gießen, und hat das Problem damit gelöst:
VB.NET-Quellcode
- Private Sub PostenBindingSource_ListChanged(ByVal sender As Object, ByVal e As ListChangedEventArgs) Handles PostenBindingSource.ListChanged
- If e.ListChangedType > ListChangedType.ItemDeleted Then Return 'lässt nur .ItemAdded, .ItemDeleted und .Reset passieren
- PostenBindingSource.AllowNew = PostenBindingSource.Count < ArtikelBindingSource.Count
- End Sub
Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „ErfinderDesRades“ ()