Benutzer mit den meisten Antworten
DataBinding an Array in Windows Forms unter Visual Basic 2013

Frage
-
Guten Morgen alle miteinander,
ich erstelle mit VB.NET unter Visual Studio 2013 ein Formular, das in einer Groupbox eine variable Anzahl von Checkboxen enthält, deren Inhalt ich an ein Boolean-Array binden möchte.
Die Datenbindung stelle ich mir in folgender Form vor:
MyGroupBox.Controls("MyCheckbox0").DataBindings.Add(New Binding("Checked", Me, "MyBooleanArray(0)"))
wobei die 0 im Namen "MyCheckbox0" und im Adressierungsausdruck "MyBooleanArray(0)" mit der tatsächlichen Checkbox von 0 bis Anzahl der Checkboxen -1 variiert. Ich hoffe, mich einigermaßen verständlich ausgedrückt zu haben.
Die Zuweisung mit "MyBooleanArray(0)" klappt so natürlich nicht.
Kann mir jemand helfen, wie der DataBindings-Ausdruck richtig erstellt werden muss? Ganz sicher gibt es auch eine elegantere Möglichkeit. Wichtig für mich ist lediglich, dass ich nach dem Schließen des Formulars ein Abbild der angeklickten Checkboxen in einem Array oder einer Liste oder wo auch immer haben werde, die ich mit einem Index von 0 bis Anzahl der Checkboxen -1 auslesen kann.
Gruß, Werner
WM
Antworten
-
Hi Werner,
eine Datenquelle an die GroupBox zu binden und zu erwarten, dass dann eine passende Anzahl Steuerelemente innerhalb der GroupBox generiert wird, ist falsch. Auf Basis des Arrays musst Du die CheckBoxes incl. Bindung und Position erzeugen und der GrupBox zuweisen.Public Class Form30 Private gb As New GroupBox With {.Dock = DockStyle.Fill, .Text = "GroupBox mit ChexBoxes"} Private rnd As New Random Private Sub Form30_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' GropBox anzeigen Me.Controls.Add(gb) ' Daten laden For i = 0 To Me._arr.GetUpperBound(0) Arr(i) = rnd.NextDouble < 0.5 Next ' GroupBox füllen ind jede CheckBos binden For i = 0 To Me._arr.GetUpperBound(0) Dim cb As New CheckBox With {.Text = $"Box {i + 1}", .Top = i * 20} cb.DataBindings.Add("Checked", Arr(i), "") gb.Controls.Add(cb) Next End Sub Private _arr(9) As Boolean ' Boolean-Array Friend Property Arr(index As Integer) As Boolean Get Return Me._arr(index) End Get Set(value As Boolean) Me._arr(index) = value End Set End Property End Class
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Bearbeitet Peter Fleischer Montag, 15. Januar 2018 09:20
- Als Antwort vorgeschlagen Peter Fleischer Montag, 15. Januar 2018 09:20
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 30. Januar 2018 07:59
-
Hi Werner,
wenn Du mit dem Designer eine Datenquelle zuweisen willst, dann muss diese auch als instanziierbare Komponente bereitstehen. Meist ist das aber nicht notwendig, da eine Zuweisung zur Ausführungszeit völlig ausreichend sein kann.--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Als Antwort markiert WerMil Dienstag, 30. Januar 2018 09:05
Alle Antworten
-
Hi Werner,
eine Datenquelle an die GroupBox zu binden und zu erwarten, dass dann eine passende Anzahl Steuerelemente innerhalb der GroupBox generiert wird, ist falsch. Auf Basis des Arrays musst Du die CheckBoxes incl. Bindung und Position erzeugen und der GrupBox zuweisen.Public Class Form30 Private gb As New GroupBox With {.Dock = DockStyle.Fill, .Text = "GroupBox mit ChexBoxes"} Private rnd As New Random Private Sub Form30_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' GropBox anzeigen Me.Controls.Add(gb) ' Daten laden For i = 0 To Me._arr.GetUpperBound(0) Arr(i) = rnd.NextDouble < 0.5 Next ' GroupBox füllen ind jede CheckBos binden For i = 0 To Me._arr.GetUpperBound(0) Dim cb As New CheckBox With {.Text = $"Box {i + 1}", .Top = i * 20} cb.DataBindings.Add("Checked", Arr(i), "") gb.Controls.Add(cb) Next End Sub Private _arr(9) As Boolean ' Boolean-Array Friend Property Arr(index As Integer) As Boolean Get Return Me._arr(index) End Get Set(value As Boolean) Me._arr(index) = value End Set End Property End Class
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Bearbeitet Peter Fleischer Montag, 15. Januar 2018 09:20
- Als Antwort vorgeschlagen Peter Fleischer Montag, 15. Januar 2018 09:20
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 30. Januar 2018 07:59
-
Hallo Peter,
und vielen Dank für Deine schnelle Antwort.
Dass die CheckBoxes generiert werden müssen ist klar und habe ich auch so gemacht. Mir kam es lediglich auf das Databinding an.
Und das schein ja mit
cb.DataBindings.Add("Checked", Arr(i), "")
wesentlich einfacher zu sein, als ich erwartet hatte.
Ich werde erst im Lauf der Woche dazu kommen es zu testen. Ich gehe aber schon mal davon aus, dass es genau so funktionieren wird. Ich melde mich nach dem Test zurück.
Nochmals vielen Dank.
Gruß, Werner
WM
-
Hi Werner,
du kannst einfach den von mir geposteten Quelltext in eine leere Form kopieren und sehen, dass es funktioniert. Wichtig in der Demo ist, dass der Zugriff für die Bindung über eine indizierte Eigenschaft gemappt wird.
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Bearbeitet Peter Fleischer Montag, 15. Januar 2018 10:17
-
Hallo Peter,
ich konnte mir einen schnellen Test in meinem bereits erstellten Code nicht verkneifen. Das hat aber nicht funktioniert. Der Code wird fehlerfrei kompiliert. Aber weder zeigen mir die entsprechenden CheckBoxes voreingestellte Werte an noch enthält das Array nach Schließen des Formulars angeklickte Werte.
Vielleicht liegt es daran, dass ich das Binding erst zuordne, nachdem ich die Checkbox bereits mit Add der GroupBox zugewiesen hatte. In Deinem Code passiert das vor dem Zuordnen.
Zu mehr reicht mir im Moment nicht die Zeit. Ich muss es, wie gesagt, im Laufe der Woche in Ruhe analysieren. Sollte ich den Fehler nicht finden, melde ich mich noch einmal mit Codeauszug.
Danke vorerst.
Gruß, Werner
WM
-
Hallo Peter,
ich nutze immer mal die Zeit zwischendurch, um zu testen und weiter zu kommen.
Vom Code her sehe ich keinen Unterschied, bis auf die oben erwähnte Zuordnung des Binding, was bei Dir vor und bei mir nach dem Add der Checkboxen zur Groupbox erfolgt. Aber daran liegt es definitiv nicht. Das habe ich schon mal ausgeschlossen.
Da ich einen Teil des Codes in Funktionen und Routinen habe, ist es mir gegenwärtig noch zu aufwändig, den ganzen Code hier einzufügen oder vorher entsprechend aufzuarbeiten.
Was mir aber noch aufgefallen ist: Du hast den Code vollständig im Load-Event des Formulars stehen. Ich dagegen habe ein Formular mit Überschrift, Buttons, Groupbox usw. und einer Checkbox bereits vorbereitet und stelle das Formular vor seinem Aufruf mit ShowDialog durch externen Code fertig. Ansonsten müsste ich zu viele Parameter übergeben. Dabei übernehme ich Eigenschaften der vordefinierten Checkbox für die Definition weiterer Checkboxen. Das Binding allerdings füge ich, ebenfalls noch vor dem Formularaufruf, für alle Checkboxen, auch für die vordefinierte, ebenfalls durch externen Code zu. Für die vordefinierte Checkbox kann ich kein Binding zuweisen, da mir das Array nicht zur Auswahl gestellt wird (Alle anderen Eigenschaften kann ich auswählen).
Vermutlich liegt der Fehler in der externen Binding-Zuordnung. Aber wie gesagt, das sieht bei mir auch nicht anders aus.
Vielleicht fällt Dir noch etwas auf/ein, bevor ich meinen Code hierher zerpflücke.
Gruß, Werner
WM
-
Hi Werner,
ob vor dem Einfügen oder nach dem Einfügen der CheckBoxes in die GroupBox die Datenbindung hinzugefügt wird, ist egal:For i = 0 To Me._arr.GetUpperBound(0) Dim cb As New CheckBox With {.Text = $"Box {i + 1}", .Top = i * 20} gb.Controls.Add(cb) cb.DataBindings.Add("Checked", Arr(i), "") Next
Ich habe nur alles im Form_Load eingefügt, damit das Beispiel auch voll funktionsfähig ist ohne weitere Designer-Aktivitäten. In einem realen Projekt ist das alles normalerweise viel komplexer. Bei dieser Komplexität kann man aber schneller Fehler machen, was bei Dir vermutlich vorliegt.
Du kannst das auch alles auslagern:
Public Class Form30 Private gb As New GroupBox With {.Dock = DockStyle.Fill, .Text = "GroupBox mit ChexBoxes"} Private dl As New Form30DataLayer Private Sub Form30_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' GroupBox füllen gb.Controls.AddRange(dl.GetCheckBoxes.ToArray) ' GropBox anzeigen Me.Controls.Add(gb) End Sub End Class Friend Class Form30DataLayer Private rnd As New Random Friend Sub New() ' Daten laden For i = 0 To Me._arr.GetUpperBound(0) Arr(i) = rnd.NextDouble < 0.5 Next End Sub Friend Iterator Function GetCheckBoxes() As IEnumerable(Of CheckBox) ' CheckBoxes erstellen und jede CheckBos binden For i = 0 To Me._arr.GetUpperBound(0) Dim cb As New CheckBox With {.Text = $"Box {i + 1}", .Top = i * 20} cb.DataBindings.Add("Checked", Arr(i), "") Yield cb Next End Function Private _arr(9) As Boolean ' Boolean-Array Private Property Arr(index As Integer) As Boolean Get Return Me._arr(index) End Get Set(value As Boolean) Me._arr(index) = value End Set End Property End Class
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Danke Peter für Deine schnellen Antworten.
Mir scheint, dass das externe Array Schuld ist. Denn es wird mir ja beim Formularentwurf auch nicht als Bindingsource angezeigt. Andererseits sollte es dann aber, nach der externen Zuweisung der Bindingsource, wohl zu Fehlern in der Laufzeit führen.
Wie Du schon richtig bemerkt hast, ist alles ziemlich komplex und sicher wird der Fehler irgendwo darin liegen.
Ich werde auf jeden Fall noch suchen und mich melden. Ich muss leider hauptsächlich einiges anderes fertigstellen.
Gruß, Werner
WM
-
Hi Werner,
wenn Du mit dem Designer eine Datenquelle zuweisen willst, dann muss diese auch als instanziierbare Komponente bereitstehen. Meist ist das aber nicht notwendig, da eine Zuweisung zur Ausführungszeit völlig ausreichend sein kann.--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Als Antwort markiert WerMil Dienstag, 30. Januar 2018 09:05
-
Hallo Peter,
vielen Dank noch einmal für alle Deine Tipps. Wie befürchtet konnte ich leider in den letzten Tagen an der Angelegenheit nicht dran bleiben und vermutlich werde ich es auch eine ganze Weile zurückstellen müssen.
Im Prinzip hattest Du aber meine Frage gleich am Anfang beantwortet, so dass jetzt eigentlich nur noch die Fehlersuche offen bleibt, die ich vermutlich alleine zum Ende bringen kann.
Ich werde daher zunächst erst einmal den Thread als beantwortet markieren. Ggf. müsste ich mich erneut melden.
Gruß, Werner
WM