custom WinForms-BindingSource: interne Liste als Datenquelle rebelliert im Designer [gelöst]

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    custom WinForms-BindingSource: interne Liste als Datenquelle rebelliert im Designer [gelöst]

    Hallo zusammen.

    Ich habe folgende Test-BindingSource-Klasse:

    VB.NET-Quellcode

    1. Public Class BS : Inherits BindingSource
    2. Private ReadOnly InternalList As New ComponentModel.BindingList(Of MyOwnClass)
    3. Public Sub New()
    4. DataSource = GetType(MyOwnClass)
    5. End Sub
    6. Private Sub BS_DataSourceChanged(sender As Object, e As EventArgs) Handles Me.DataSourceChanged
    7. If DataSource IsNot InternalList Then DataSource = InternalList
    8. End Sub
    9. Public Overloads Sub Add(NewItem As MyOwnClass)
    10. InternalList.Add(NewItem)
    11. End Sub
    12. End Class

    und dazu noch:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. Bs1.Add(New MyOwnClass With {.ID = 0, .Name = "Foo"})
    4. End Sub
    5. End Class
    6. Public Class MyOwnClass
    7. Property ID As Integer
    8. Property Name As String
    9. End Class

    Wenn ich das kompiliere und mir die BS auf's Form ziehe, kommt mir ne Exception, weil MyOwnClass nicht als serialisierbar gekennzeichnet ist (Bild 1). Schließen oder speichern kann ich den Designer des Forms auch nicht (Bild 2). Und löschen kann ich die BS aus dem Form dann auch nicht mehr, da ebenfalls die Exception kommt (Bild 2), also muss ich über die FormX.Designer.VB das Ganze löschen.
    Ich kann aber das Teil auf's Form hauen, die Exception wegklicken, zu einem anderen Dateitab switchen und dann den FormX-Designer-Tab schließen und wieder aufrufen und der Fehler ist erstmal gegessen. Das Programm läuft auch ganz normal. Ist aber trotzdem dämlich.
    Ich habe zwar einen Workaround gefunden. Aber schön sieht anders aus.

    VB.NET-Quellcode

    1. Private Sub BS_DataSourceChanged(sender As Object, e As EventArgs) Handles Me.DataSourceChanged
    2. If Diagnostics.Debugger.IsAttached AndAlso DataSource IsNot InternalList Then DataSource = InternalList '
    3. End Sub

    Hat mir da jemand eine Erklärung zu dem Problem und (bessere) Lösung dazu?

    ##########

    Ah, bevor jemand das als Lösung postet: MyOwnClass mit dem Attribut <Serializable> zu kennzeichnen ist für mich inakzeptabel, da ich nicht mit Attributen arbeiten will.
    Bilder
    • Bild 1.png

      12,14 kB, 412×472, 63 mal angesehen
    • Bild 2.png

      4,45 kB, 357×184, 62 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    VaporiZed schrieb:

    da ich nicht mit Attributen arbeiten will.
    Hast Du es wenigstens mal probiert?
    Andererseits ist das sehr merkwürdig, denn wenn ich mir das Beispiel in den Cods ansehe, kommt das da auch nicht vor:
    docs.microsoft.com/de-de/dotne…nglist-1?view=netcore-3.1
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, hatte ich natürlich, und damit klappt es auch.
    Zwischen dem Beispiel im von Dir gegebenen Link und meinem Fall kann ich aus 2 Punkten nichts abgewinnen. Von einer BindingSource ist nicht die Rede und die BindingList-Instanziierung erfolgt erst im Form-Load-Event. Mein Beispiel zielt aber darauf ab, die DataSource bereits im Designer initialisiert zu haben. Das ist ja auch der Punkt, warum es mit Debugger.IsAttached funktioniert. Das greift ja erst zur Laufzeit, ist also so, als ob ich die DataSource erst im z.B. Form-Load-EventHandler setze. Mein Problem damit: Man müsste immer daran denken, diese Initialisierung explizit aufzurufen. Sowas will ich vermeiden. Da der Code von DAUs verwendet werden wird. Und der größte DAU bin immer noch ich (obwohl sich da die Frage stellt, ob man DAU überhaupt steigern kann …), weil ich als User meiner Controls denkfaul bin und daher versuche, als Control-Entwickler das Ergebnis User-denkfaul wie möglich zu gestalten.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    VaporiZed schrieb:

    ob man DAU überhaupt steigern kann …
    • ADAU (der aller dümmste ...)
    • NDAU (der noch dümmere ...)
    :thumbsup:
    ====
    Kann es sein, dass derade das Binden im Designer das Serializable erfordert, um das Projekt auf Platte zu speichern?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Tja, das ist eben das komische an der Sache. Hab ich erstmal die Exception-Widrigkeiten beseitigt (s. Post#1 mit den Dateitabs), kann ich das Projekt problemlos abspeichern, mir das Form im Designer anschauen und die App auch starten. Nur das Modifizieren der BS (neue hinzufügen, löschen) rebelliert. Oder anders: Anfangs rebelliert das verfluchte Teil, danach ist es halbwegs brav (wenn man es in Ruhe lässt, nicht nass macht und nicht nach Mitternacht füttert).

    ##########

    Ach ja, wenn ich probiere, einer normalen BS in der Designer.vb als DataSource eine Listen/BindingList-Instanz unterzujubeln, kommen andere Exceptions, die eine Benutzung komplett unmöglich machen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    VaporiZed schrieb:

    da ich nicht mit Attributen arbeiten will.
    Ichtäte dir ein anneres Attribut vorschlagen, nämlich DesingerSerialisazion.Visible(never) für die DataSource deiner bindingSource.
    Ich vermute nämlich einen Zusammenhang der Designer-Spinnerei dadurch, dass der Designer deiner BS eine DataSource andrehen will - aber bei deine BS ist die ja schon vorbestimmt.
    Ich weiß, Du meinst, was Du schreibst. Da das von Dir vorgeschlagene Attibut aber nicht exisiert, habe ich das schreibtechnisch naheliegende <ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)> auf die InternalList angewandt. Leider ohne Erfolg. Selbe Exception.

    Ach, Moment. Erfolgreich falsch implementiert. Wenn ich die DataSource entsprechend modifiziere, scheint es zu klappen.

    VB.NET-Quellcode

    1. <ComponentModel.DesignerSerializationVisibility(ComponentModel.DesignerSerializationVisibility.Hidden)>
    2. Shadows Property DataSource As Object


    ##########

    Hm, die Exception kommt nicht mehr. Dafür kann ich kein ComplexBinding mehr anwenden. Will heißen, wenn ich eine ListBox an die BS anbinde, kann ich nicht mehr auf die Properties von MyOwnClass zugreifen und sie in der ListBox als DisplayMember und ValueMember einstellen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Ich sollte klarstellen: Grundsätzlich würde Dein Vorschlag wohl funktionieren. Ich weiß nur nicht, wie ich die originale DataSource-Property mit einem Attribut versehen kann. Denn die Einstellmöglichkeiten im Designer für das ComplexBinding verschwinden nicht durch das Attribut, sondern durch die Tatsache, dass ich die DataSource-Property mittels Shadows oder Overloads quasi neu definiere. Habe nämlich gesehen, dass ein Haufen Zusatzcode in der originalen Property abläuft - oh Wunder, oh Wunder. Nur weiß ich nicht, wie ich den quasi behalten kann und die Property trotzdem mit einem Attribut versehen kann.
    Oder kurz: Wie versehe ich die originale DataSource-Proiperty mit einem Attibut - ohne den kompletten BS-SourceCode zu verwenden und mir die BS quasi neu zu schreiben.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich habe jetzt doch noch was gefunden, was besser als der Post#1 Workaround ist, da "gezielter" und somit sicherer. Mit dem neuesten VS-Update 16.8.4 hat der Workaround aus Post#1 nämlich nicht mehr funktioniert.
    Statt

    VB.NET-Quellcode

    1. Private Sub BS_DataSourceChanged(sender As Object, e As EventArgs) Handles Me.DataSourceChanged
    2. If Diagnostics.Debugger.IsAttached AndAlso DataSource IsNot InternalList Then DataSource = InternalList
    3. End Sub

    läuft nun (vorerst zuverlässig)

    VB.NET-Quellcode

    1. Private Sub BS_DataSourceChanged(sender As Object, e As EventArgs) Handles Me.DataSourceChanged
    2. If System.ComponentModel.LicenseManager.UsageMode = System.ComponentModel.LicenseUsageMode.Runtime AndAlso DataSource IsNot InternalList Then DataSource = InternalList
    3. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.