Von Innerer Klasse auf Property äußerer Klasse zugreifen

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Vatter.

    Von Innerer Klasse auf Property äußerer Klasse zugreifen

    Hey,

    Ich habe eine Form mit 2 Datagridviews. Außerdem habe ich in der Form selbst eine Bindinglist, die Bücher enthält. Die Bindinglist(of Books) ist an dgvBooks gebunden.
    Die Klasse Book ist außerhalb der Form definiert und enthält eine Bindinglist(of Chapter). Die Klasse Chapter ist innerhalb der Klasse Book definiert.
    Es gibt eine Eigenschaft der Buchklasse (Titel), auf die ich auch in der Klasse Chapter zugreifen will (lesen und ändern). Denn wenn jemand den Buchtitel im DGV ändern sollte, dann soll Buchtitel in beiden DGV's synchron geändert werden.
    Je nachdem welches Buch im dgvBooks gerade ausgewählt ist, werden die entsprechenden Kapitel im dgvChapters angezeigt.

    Eine Möglichkeit wäre es Im Konstruktor der Chapter Klasse eine Referenz auf das Buch zu übergeben. Das finde ich aber nicht so sauber.
    Wieso werden eigentlich die Kapitel nicht mit zerstört, wenn ich zum Beispiel ein Buch aus der Bindinglist(of Books) entferne? Die Kapitel werden weiterhin im 2. DGV dargestellt (solange ich die .DataSource nicht ändere).
    Existiert ein Objekt solange, bis keine Referenz mehr darauf existiert?

    Form1

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Property Books As New BindingList(Of Book)
    3. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs)
    4. dgvBooks.SelectionMode = DataGridViewSelectionMode.FullRowSelect
    5. End Sub
    6. Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    7. 'Testdaten einfügen
    8. Dim bk1 As New Book("eins", "11", "111")
    9. Dim bk2 As New Book("zwei", "22", "222")
    10. For i = 1 To 4
    11. bk1.AddChapter("Kapitel 1")
    12. bk2.AddChapter("Kapitel 2")
    13. Next
    14. Books.Add(bk1)
    15. Books.Add(bk2)
    16. dgvBooks.DataSource = Books
    17. End Sub
    18. Private Sub dgvBooks_SelectionChanged(sender As System.Object, e As System.EventArgs) Handles dgvBooks.SelectionChanged
    19. If dgvBooks.SelectedCells.Count <> 0 Then
    20. Dim rowindex As Int32 = dgvBooks.SelectedCells.Item(0).RowIndex
    21. dgvChapters.DataSource = CType(dgvBooks.Rows(rowindex).DataBoundItem, Book).Chapters
    22. Else
    23. dgvChapters.DataSource = Nothing
    24. End If
    25. End Sub
    26. End Class

    Book

    VB.NET-Quellcode

    1. Public Class Book
    2. Private Property _Title As String
    3. Private Property _Subtitle As String
    4. Private Property _Authors As String
    5. Private Property _Chapters As New BindingList(Of Chapter)
    6. Public Sub New(Title As String, Subtitle As String, Authors As String)
    7. _Title = Title
    8. _Subtitle = Subtitle
    9. _Authors = Authors
    10. End Sub
    11. Public Sub AddChapter(ChapterTitle As String)
    12. _Chapters.Add(New Chapter(ChapterTitle))
    13. End Sub
    14. Public Property Title As String
    15. Get
    16. Return _Title
    17. End Get
    18. Set(value As String)
    19. _Title = value
    20. Chapters.ResetBindings()
    21. End Set
    22. End Property
    23. Public Property Subtitle As String
    24. Get
    25. Return _Subtitle
    26. End Get
    27. Set(value As String)
    28. _Subtitle = value
    29. End Set
    30. End Property
    31. Public Property Authors As String
    32. Get
    33. Return _Authors
    34. End Get
    35. Set(value As String)
    36. _Authors = value
    37. End Set
    38. End Property
    39. Public ReadOnly Property Chapters As BindingList(Of Chapter)
    40. Get
    41. Return _Chapters
    42. End Get
    43. End Property
    44. Class Chapter
    45. Private Property _ChapterTitle As String
    46. Public Sub New(ChapterTitle As String)
    47. _ChapterTitle = ChapterTitle
    48. End Sub
    49. Public Property BookTitle As String
    50. Get
    51. Return "????" 'Hier muss der Titel des Buches zurückgegeben werden
    52. End Get
    53. Set(value As String)
    54. 'Hier muss der Titel des Buches geändert werden
    55. End Set
    56. End Property
    57. Public Property ChapterTitle As String
    58. Get
    59. Return _ChapterTitle
    60. End Get
    61. Set(value As String)
    62. _ChapterTitle = value
    63. End Set
    64. End Property
    65. 'Noch mehr Propertys...
    66. End Class
    67. End Class
    Schau dir mal Daten laden und speichern vom Erfinder des Rades an.
    Ein typisiertes Dataset erlaubt dir, diese Anwendung recht einfach und ohne viel Codegeschreibsel umzusetzen. Dazu brauchts auch keine Datenbank. Das ganze lässt sich als XML wegspeichern und zurückholen.
    Und gerade das Löschproblem bekommst du sehr einfach gelöst. Das macht nämlich alles dein Datataset selbständig.

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Also das Löschproblem bereitet mir keine wirklichen Probleme. Meine Frage war eher eine "Verständnisfrage", wieso VB sich so verhält, bzw. WANN GENAU ein Object gelöscht wird.
    Der von dir verlinkte Post hilft mir nicht weiter. Speichern/laden in XML wird nicht notwendig sein.
    Mein Problem ist momentan mein Klassenkonzept. Dieses hindert mich daran in der Klasse Chapter auf den Buchtitel zuzugreifen.
    Wie löse ich das am besten?

    markus.obi schrieb:

    Wie löse ich das am besten?
    Indem du beim Erzeugen einer Instanz von Chapter eine Instanz von Book mitgibst oder auf das Verändern des Booktitles aus der Klasse Chapter heraus verzichtest. Ich wüßte keinen Grund, warum die Radmutter eines Autos auf die Farbeigenschaft des Autos zugreifen sollte ;)
    Einfacher wäre aber, du würdest ein typisiertes Dataset mit entsprechenden Tabellenbeziehungen verwenden. Da verfügt die Tabelle Chapter dann über die ID des Books. Und deine Anwendung ist in dem von dir gezeigten ausschnitt eine 1a Datenanwendung mit 2 Tabellen und 1:n Beziehung. Das wäre in 10Minuten zusammengeklickt und würde dir auch dein leidiges Aktualisierungsproblem ersparen.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    markus.obi schrieb:

    Wieso werden eigentlich die Kapitel nicht mit zerstört, wenn ich zum Beispiel ein Buch aus der Bindinglist(of Books) entferne?
    Das hängt davon ab, wie du dieses hier zuwegegebracht hast:

    markus.obi schrieb:

    Je nachdem welches Buch im dgvBooks gerade ausgewählt ist, werden die entsprechenden Kapitel im dgvChapters angezeigt.
    Wären die Grids über BindingSources an die Daten gebunden, so würde die Kapitel-Anzeige auch verschwinden, wenn ein Buch gelöscht wird.
    @ErfinderDesRades

    Ich hatte auch ursprünglich vor mit Bindings zu arbeiten. Leider habe ich auf den Gebieten DataGridView, Binding, "typisiertes Dataset" noch gar keine Erfahrung.
    DataGridView.DataSource schien auf den ersten Blick erstmal ziemlich bequem.
    Ich hatte mir auch mal deinen Beispielcode zu Progressbar im DatagridView - benutzerdefiniertes Databinding angeschaut. So ganz durchgeblickt habe ich da noch nicht.

    @80%GroßVatter

    Die Aktualisierung wäre mit dem jetzigen Model auch schlecht machbar, weil die Bookklasse nicht auf die BindingList(of Book) zugreifen kann.

    Vatter schrieb:

    Das wäre in 10Minuten zusammengeklickt

    Bei DIR 10 Minuten. Ich muss mich da erstmal reinarbeiten :wacko:
    OK, mal ne Schnellanleitung, die jedoch keinen Anspruch auf Vollständigkeit erhebt und nur den groben Ablauf schildern soll:
    1. Dem Projekt ein Dataset hinzufügen und öffnen (Gute Namensgebung nicht vergessen, sonst gibt es so Monsterbezeichnungen)
    2. Im Dataset-Designer aus der Toolbox 2 Tabellen ziehen und diese benennen
    3. Den Tabellen Spalten hinzufügen (Strg + L)
    Tabelle Books: ID, Titel,...
    Tabelle Chapters: ID, Name, BookID
    4. Den Spalten im Eigenschaftenfenster die Datentypen zuweisen. Dabei den ID und der BookID Integer
    5. Die ID-Spalten als Key kennzeichnen (rechte Maustaste)
    6. Die Spalte ID der Tabelle Books mit der Maus zur Spalte BookID der Tabelle Chapter ziehen. Es wird eine Tabellenbeziehung 1:n erzeugt. An der Book-Tabelle müsste jetzt ein Schlüssensymbol und am anderen Ende ein unendlich hängen. D.h. es gibt zu jedem Book-Datensatz 0 bis unendlich viele Chapters-Datensätze
    7. Auf den Formdesigner wechseln und das Datenquellen-Fenster öffnen.
    Im Datenquellen siehst du jetzt die beiden Tabellen, wovon die Books-Tabelle die Chapters-Tabelle als Untertabelle (Child) zeigt.
    8. Ziehe nacheinander die übergeordnete und die untergeordnete Tabelle auf deine Form

    Damit hast du bereits eine testfähige Version fertig. Wenn du 1 Book markierst, werden die zugehörigen Chapters angezeigt.
    Was noch fehlt ist z.B. Autoinkrement, um die IDs nicht manuell eintragen zu müssen und die Löschweitergabe sowie Laden und speichern der Daten.

    Ich empfehle dir, mal bei Erfinder des Rades nach Datenbank in 10 Minuten und DatasetOnly zu suchen. Das sind ganz ausgezeichnete Tuts, die du mal (unbedingt 1:1) durchspielen solltest. Ich kann dir versprechen, dass du nie wieder ähnliche Anwendungen anders realisieren wirst. Es lässt sich fast alles damit anstellen, ohne dass man viel herumcoden muß.

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup: