CustomDGV, Datasource, Serializable, Token Error

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Rootbob91.

    CustomDGV, Datasource, Serializable, Token Error

    Guten Tag,

    ich sitze nun schon seit mehreren Stunden an folgendem Problem.

    Ich möchte einem Datagridview bei der Instanzierung im Sub New, eine neu hinzugefügte Eigenschaft von sich selbst als Datasource verwenden. Das will nicht :(...


    Seit Stunden probiere ich hier rum und versuchs zu lösen, ich kriegs nicht hin und langsam verzweifel ich :cursing: :cursing: .

    Ich habe euch das Projekt mal hochgeladen, entfernt zur Nachstellung einfach nur das "'" innerhalb der Sub New und packt das Control testweise auf eure Form..

    Alternativ: Kopiert den Code von hier, falls ihr nicht downloaden wollt:
    "Problemcode :("

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. 'CustomDGV1.foos = New List(Of foo) From {New foo("blaaaa", 1)}
    5. End Sub
    6. End Class
    7. Public Class CustomDGV : Inherits DataGridView
    8. Private _foos As List(Of foo)
    9. Public Property foos() As List(Of foo)
    10. Get
    11. Return _foos
    12. End Get
    13. Set(ByVal value As List(Of foo))
    14. _foos = value
    15. End Set
    16. End Property
    17. Sub New()
    18. 'Me._foos = New List(Of foo)
    19. Me.DataSource = Me._foos
    20. End Sub
    21. End Class
    22. Public Class foo
    23. Private _Text As String
    24. Public Property Text() As String
    25. Get
    26. Return _Text
    27. End Get
    28. Set(ByVal value As String)
    29. _Text = value
    30. End Set
    31. End Property
    32. Private _ID As Integer
    33. Public Property ID() As Integer
    34. Get
    35. Return _ID
    36. End Get
    37. Set(ByVal value As Integer)
    38. _ID = value
    39. End Set
    40. End Property
    41. Sub New()
    42. End Sub
    43. Sub New(t As String, i As Integer)
    44. Me._Text = t
    45. Me._ID = i
    46. End Sub
    47. End Class



    PS!!!:
    - Implementierung des Serializable Interface bereits versucht
    - Bei einer Google Suche stieß ich auf die Meinung einer Person, dass man keinen generischen Code verwenden soll blabla im Sub New, deshalb hatte ich auch testweise von System.Collections.Generic.List (o.ä...) auf normale Arrays umgebaut, aber das wollte auch nicht :(!
    Dateien
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..

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

    Ist das viel Arbeit?

    Wie genau serialisieren, reicht die Setzung des Serializable-Attributes, oder muss dies komplett implememtiert werden mit GetObjectData oder wie die Funktion nochmal hieß? Kommt das dann in die einzelne Klasse foo, oder wie geht das? Würdest du bitte helfen?!

    Das wäre echt göttlich wenn ich das noch hinbekommen würde, liege zwar gerade schon im Bett, aber dann würde ich nochmal rausspringen um das Erfolgserlebnis zu catchen :0 :D

    Grüße zurück :)!
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..
    so serialisierst du das

    Deine Klasse aus der du die List of erstellen willst

    VB.NET-Quellcode

    1. <Serializable()> _
    2. Public Class foo
    3. '.....


    und dann dein Code

    VB.NET-Quellcode

    1. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    2. Private _foos As List(Of foo)
    3. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    4. Public Property foos() As List(Of foo)
    5. Get
    6. Return _foos
    7. End Get
    8. Set(ByVal value As List(Of foo))
    9. _foos = value
    10. End Set
    11. End Property


    hoffe es ist so richtig, so funktioniert es bei mir in der Outbar
    Meine Projekte Genesis Game Engine | GFX | smartli.me - Der smarte URL shortener

    Verdammte kacke xD.. So ähnlich hatte ich das vorhin mal, ich hatte das einmal auf Hidden stehen und einmal auf Content, allerdings (und jetzt kommt wahrscheinlich der Fail) nur 1x.

    Du hast das ja für Property sowie für die Private Variable gesetzt gehabt, dass hatte ich nicht T.T..

    Wäre geil wenns jetzt gelöst ist, ich hüpf mal raus und probiers aus :)!

    Auf jeden Fall danke soweit! ;)


    EDIT:
    Habs ausprobiert, leider kommt dann der angehangene Fehler :/ ;(!
    Nun ist noch ne kleine Info/Warnung hinzugekommen.
    Bilder
    • AAAA-ERROR.PNG

      17 kB, 1.590×101, 129 mal angesehen
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Rootbob91“ ()

    Nene, hab extra n frische Projekt aufgemacht, den Code so reingehauen einmal gedebuggt damit das Control in der Toolbox erscheint, auf die Form gezogen Debuggen - Fehler.

    Was mir gerade noch aufgefallen ist: Instanziere ich das Control während der Laufzeit und via manuellem ..Controls.Add() dann klappt es. Über die Toolbox allerdings nicht, wobei das einer mit der größten Vorteile wäre.
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..

    Rootbob91 schrieb:

    Ich möchte einem Datagridview bei der Instanzierung im Sub New, eine neu hinzugefügte Eigenschaft von sich selbst als Datasource verwenden. Das will nicht
    Sei froh, denn die Idee taugt glaub nix.
    Nimm ein normales DGV, und gib ihm als Datasource die List(Of Foo)

    Wie bist du auf die Idee verfallen, die List(Of Foo) müsste eine zusätzliche Property des DGVs sein?
    Nun musste der Property einen Wert geben - denselben, den du zuvor der Datasource gegeben hättest.
    Also was ist der Gewinn - ausser dass der FormDesigner spinnt?
    Du musst bei Zuweisung von

    VB.NET-Quellcode

    1. CustomDGV1.foos = New List(Of foo) From {New foo("blaaaa", 1)}

    im PopertySetter von Property foos die Datasource neu initialisieren (Zeile 10). Zeile 17 weist nämlich ein Objekt des Wertes NOTHING zu. Selbst bei Übernahme des auskommentierten Wertes in Zeile 15 würde eine leere List(of foo) zugewiesen


    VB.NET-Quellcode

    1. Public Class CustomDGV : Inherits DataGridView
    2. Private _foos As List(Of foo)
    3. Public Property foos() As List(Of foo)
    4. Get
    5. Return _foos
    6. End Get
    7. Set(ByVal value As List(Of foo))
    8. _foos = value
    9. Me.DataSource = Me._foos
    10. End Set
    11. End Property
    12. Sub New()
    13. 'Me._foos = New List(Of foo)
    14. Me.DataSource = Me._foos
    15. End Sub
    16. End Class

    Zu meinem Verständnis: Warum der Umweg über die Property foos ? Direkte Zuweisung auf Datagridview.Datasource ergäbe das gleiche Ergebnis ...

    //Edit:
    @ErfinderDesRades war schneller ... sorry.
    Also allg. dachte ich mir das so:
    Ich habe ungefähr an die 100 DGVs die Daten speichern, bzw. eher anzeigen müssen.
    Und dann müsste ich sozusagen 100 getrennt Lists of anlegen und diese dem Datasource extra zuweisen.

    Dann dachte ich mir gut, dann machste dir n DGV, welches die zu speichernden Daten als Eigenschaft hat, dann noch ne Funktion/Sub mit der du neue Items hinzufügst und die Enthaltenen kannst du dann über die Getter abfragen und bearbeiten.

    An sich funktioniert das DGV jetzt.. Das einzige was noch n bisschen doof ist, ist das ich es nicht aus der Toolbox auf die Form ziehen kann, da gibt es noch ein Problem.
    Mir war schon klar, dass ihr ggf. ne bessere Lösung habt und diese auch begründet, wie EDR oben angefangen hatte. Leider blicke ich da noch nicht so ganz durch wie er das gerade meint, könnte daran liegen das ich 15 Stunden Arbeit hinter mir habe und wenig Schlaf, sorry.

    Der Datasource wird jetzt immer beim hinzufügen (über eine Sub) aktualisiert.

    Ps: Noch eine Frage hätte ich, ich habe mich zwischendurch vertan, weil ich leider auch CustomDGV1.foos.Add() geschrieben hatte, statt es über die dafür angelegte funktion zu regeln (fooHinzufügen()).
    Obwohl die Eigenschaft foos auf Readonly ist, kann ich .Add anwählen.

    Kann man das deaktivieren? Wahrscheinlich müsste ich dafür ne eigene ListOf Klasse schreiben und dann die .Add() Funktion überschreiben oder sogar darin dann deaktivieren oder?
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Rootbob91“ ()

    So habe es mal gebaut, den Source Kannst du gerne weite rausbauen, Ohne Namensnennung oder Sonstiges. Funktioniert mal bei mir.



    Grüße Andy
    Dateien
    Meine Projekte Genesis Game Engine | GFX | smartli.me - Der smarte URL shortener

    Rootbob91 schrieb:

    Ich habe ungefähr an die 100 DGVs die Daten speichern, bzw. eher anzeigen müssen.
    Und dann müsste ich sozusagen 100 getrennt Lists of anlegen und diese dem Datasource extra zuweisen.

    naja - man hätte halt 100 BindingSources auf den Forms rumzufahren.
    Was, wenn man eh 100 DGVs rumfahren hat, den Kohl auch nicht weiter fett macht.

    Rootbob91 schrieb:

    Leider blicke ich da noch nicht so ganz durch wie er das gerade meint,...
    Darum solltest du dich vlt. bemühen, denn wenn du so weiter machst, wird vmtl. demnächst niemand mehr deine Anwendung durchblicken können.
    Hi Andy, habs mal ausprobiert, leider geht es noch nicht ganz.

    Spiele jetzt schon wieder lange hier rum, allerdings gehts nicht.


    Ich hab folgendes rausgefunden (da ich immer einen Index Fehler bekomme):
    Man siehe sich die Codes an - Könnte mir das jemand erklären? Wie ich das löse?


    "Code1 - Geht nicht"

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. Dim dgv_foo As New DBTerminDGV
    5. Me.Controls.Add(dgv_foo)
    6. dgv_foo.Hinzufügen(New foo("5","sddddd"))
    7. End Sub
    8. End Class
    9. Public Class CustomDGV : Inherits DataGridView
    10. Public Event foosChanged(e As List(Of foo))
    11. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    12. Private _foos As New List(Of foo)
    13. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    14. ReadOnly Property foos() As List(Of foo)
    15. Get
    16. Return _foos
    17. End Get
    18. End Property
    19. Private _SichtbareSpalten As String() = New String() {}
    20. Public Property SichtbareSpalten() As String()
    21. Get
    22. Return _SichtbareSpalten
    23. End Get
    24. Set(ByVal value As String())
    25. _SichtbareSpalten = value
    26. For Each C As DataGridViewColumn In Me.Columns
    27. C.Visible = False
    28. Next
    29. Dim i As Integer = 0
    30. For Each Spalte As String In _SichtbareSpalten
    31. Dim Col As DataGridViewColumn = Me.Columns(Spalte)
    32. If Not IsNothing(Col) Then
    33. Col.Visible = True
    34. Col.DisplayIndex = i
    35. End If
    36. i += 1
    37. Next
    38. End Set
    39. End Property
    40. ''' <summary>
    41. ''' Setzt alle angegebenen Spalten (falls vorhanden) auf den gewählten Text. Bsp: = {"Spalte1;Text1","Spalte2;Text2"}
    42. ''' </summary>
    43. ''' <remarks></remarks>
    44. Private _Spaltenbezeichnungen As String() = New String() {}
    45. Public Property Spaltenbezeichnungen() As String()
    46. Get
    47. _Spaltenbezeichnungen = New String() {}
    48. If Me.Columns.Count > 0 Then
    49. Dim tmpList As New List(Of String)
    50. For Each col As DataGridViewColumn In Me.Columns
    51. tmpList.Add(col.HeaderText)
    52. Next
    53. _Spaltenbezeichnungen = tmpList.ToArray
    54. End If
    55. Return _Spaltenbezeichnungen
    56. End Get
    57. Set(values As String())
    58. _Spaltenbezeichnungen = values
    59. 'für jede angegebene Spaltenkonfiguration prüfen
    60. For Each Spbz As String In values
    61. 'ob eine Spalte mit der Bezeichnung vorhanden ist, wenn ja dann Text setzen
    62. For Each Col As DataGridViewColumn In Me.Columns
    63. If Col.Name = Spbz.Split(";")(0) Then Col.HeaderText = Spbz.Split(";")(1)
    64. Next
    65. Next
    66. End Set
    67. End Property
    68. Sub New()
    69. Me.DoubleBuffered = True
    70. SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint, True)
    71. Me.DataSource = Nothing
    72. Me.Refresh()
    73. Me.DataSource = _foos
    74. End Sub
    75. Sub New(T As System.Collections.Generic.List(Of foo))
    76. Me.DoubleBuffered = True
    77. SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint, True)
    78. Me.DataSource = Nothing
    79. Me.Refresh()
    80. _foos = T
    81. Me.DataSource = _foos
    82. End Sub
    83. #Region "######## METHODEN ##########################################################################################################################################################################################"
    84. Public Sub Hinzufügen(ByVal T As foo)
    85. Me.DataSource = Nothing
    86. Me.Refresh()
    87. _foos.Add(T)
    88. Me.DataSource = _foos
    89. RaiseEvent foosChanged(_foos)
    90. End Sub
    91. #End Region
    92. End Class
    93. <Serializable> _
    94. Public Class foo
    95. Private _ID As String
    96. Public Property ID() As String
    97. Get
    98. Return _ID
    99. End Get
    100. Set(ByVal value As String)
    101. _ID = value
    102. End Set
    103. End Property
    104. Private _Betreff As String
    105. Public Property Betreff() As String
    106. Get
    107. Return _Betreff
    108. End Get
    109. Set(ByVal value As String)
    110. _Betreff = value
    111. End Set
    112. End Property
    113. Sub New()
    114. End Sub
    115. Sub New(i As String, b As String)
    116. Me._ID = i
    117. Me._Betreff = b
    118. End Sub
    119. End Class


    Leider habe ich im folgenden Beispiel dann einen leeren Eintrag.. Könnte mir jmd. helfen das zu fixen?
    "Code2 - Geht!!"

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. Dim dgv_foo As New DBTerminDGV
    5. Me.Controls.Add(dgv_foo)
    6. dgv_foo.Hinzufügen(New foo With {.ID = 5, .Betreff = "sddddd"})
    7. End Sub
    8. End Class
    9. Public Class CustomDGV : Inherits DataGridView
    10. Public Event foosChanged(e As List(Of foo))
    11. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    12. Private _foos As List(Of foo) = New List(Of foo) From {New foo()}
    13. <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    14. ReadOnly Property foos() As List(Of foo)
    15. Get
    16. Return _foos
    17. End Get
    18. End Property
    19. Private _SichtbareSpalten As String() = New String() {}
    20. Public Property SichtbareSpalten() As String()
    21. Get
    22. Return _SichtbareSpalten
    23. End Get
    24. Set(ByVal value As String())
    25. _SichtbareSpalten = value
    26. For Each C As DataGridViewColumn In Me.Columns
    27. C.Visible = False
    28. Next
    29. Dim i As Integer = 0
    30. For Each Spalte As String In _SichtbareSpalten
    31. Dim Col As DataGridViewColumn = Me.Columns(Spalte)
    32. If Not IsNothing(Col) Then
    33. Col.Visible = True
    34. Col.DisplayIndex = i
    35. End If
    36. i += 1
    37. Next
    38. End Set
    39. End Property
    40. ''' <summary>
    41. ''' Setzt alle angegebenen Spalten (falls vorhanden) auf den gewählten Text. Bsp: = {"Spalte1;Text1","Spalte2;Text2"}
    42. ''' </summary>
    43. ''' <remarks></remarks>
    44. Private _Spaltenbezeichnungen As String() = New String() {}
    45. Public Property Spaltenbezeichnungen() As String()
    46. Get
    47. _Spaltenbezeichnungen = New String() {}
    48. If Me.Columns.Count > 0 Then
    49. Dim tmpList As New List(Of String)
    50. For Each col As DataGridViewColumn In Me.Columns
    51. tmpList.Add(col.HeaderText)
    52. Next
    53. _Spaltenbezeichnungen = tmpList.ToArray
    54. End If
    55. Return _Spaltenbezeichnungen
    56. End Get
    57. Set(values As String())
    58. _Spaltenbezeichnungen = values
    59. 'für jede angegebene Spaltenkonfiguration prüfen
    60. For Each Spbz As String In values
    61. 'ob eine Spalte mit der Bezeichnung vorhanden ist, wenn ja dann Text setzen
    62. For Each Col As DataGridViewColumn In Me.Columns
    63. If Col.Name = Spbz.Split(";")(0) Then Col.HeaderText = Spbz.Split(";")(1)
    64. Next
    65. Next
    66. End Set
    67. End Property
    68. Sub New()
    69. Me.DoubleBuffered = True
    70. SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint, True)
    71. Me.DataSource = Nothing
    72. Me.Refresh()
    73. Me.DataSource = _foos
    74. End Sub
    75. Sub New(T As System.Collections.Generic.List(Of foo))
    76. Me.DoubleBuffered = True
    77. SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint, True)
    78. Me.DataSource = Nothing
    79. Me.Refresh()
    80. _foos = T
    81. Me.DataSource = _foos
    82. End Sub
    83. #Region "######## METHODEN ##########################################################################################################################################################################################"
    84. Public Sub Hinzufügen(ByVal T As foo)
    85. Me.DataSource = Nothing
    86. Me.Refresh()
    87. _foos.Add(T)
    88. Me.DataSource = _foos
    89. RaiseEvent foosChanged(_foos)
    90. End Sub
    91. #End Region
    92. End Class
    93. <Serializable> _
    94. Public Class foo
    95. Private _ID As String
    96. Public Property ID() As String
    97. Get
    98. Return _ID
    99. End Get
    100. Set(ByVal value As String)
    101. _ID = value
    102. End Set
    103. End Property
    104. Private _Betreff As String
    105. Public Property Betreff() As String
    106. Get
    107. Return _Betreff
    108. End Get
    109. Set(ByVal value As String)
    110. _Betreff = value
    111. End Set
    112. End Property
    113. Sub New()
    114. End Sub
    115. Sub New(i As String, b As String)
    116. Me._ID = i
    117. Me._Betreff = b
    118. End Sub
    119. End Class


    Ps: Es funktioniert auch, wenn ich im "nicht funktionierenden Code", ein Item hinzufüge, bevor das DGV zu den Controls hinzugefügt wird, dann gehts. Andernfalls kommt der Index-Fehler..
    Selbst wenn ich nachträglich Items hinzufüge und diese auch im DGV angezeigt werden, kommt der Index-Fehler :thumbdown: :thumbdown:
    Der Fehler kommt scheinbar nur zustande, wenn das DGV eine leere Liste aufweist.

    EDIT:
    Hab den gerade beschrieben Fehler gefixt, indem ich eine Bindinglist statt der normalen List genommen habe.
    Allerdings würde ich das ggf. noch gerne hinbekommen, dass man das Control aus der Toolbox ziehen und benutzen kann und nicht diese angehangene Fehler aus Post #5
    Polling is trolling!

    Achtung: Ich habe die komische Angewohnheit, simple Dinge zu verkomplizieren..

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Rootbob91“ ()