MemberwiseClone() von Objekten die INotifyPropertyChanged implementieren

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    MemberwiseClone() von Objekten die INotifyPropertyChanged implementieren

    Hallo zusammen,

    Ich habe ein Business-Objekt:

    VB.NET-Quellcode

    1. Public Class EQ_Component
    2. Implements ICloneable
    3. Implements INotifyPropertyChanged
    4. Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    5. Public Function Clone() As Object Implements System.ICloneable.Clone
    6. Dim copy As EQ_Component = Me.MemberwiseClone()
    7. copy.ResetChangeEvent()
    8. Return copy
    9. End Function
    10. Protected Sub ResetChangeEvent()
    11. PropertyChangedEvent = Nothing
    12. End Sub
    13. Private m_ItemName As String = String.Empty
    14. Public Property ItemName As String
    15. Get
    16. Return m_ItemName
    17. End Get
    18. Set(value As String)
    19. m_ItemName = value
    20. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(EQ_Tools.GetMemberName(Function() Me.ItemName)))
    21. End Set
    22. End Property
    23. '..... viele weitere Properties dieser Art (String, Double, Long werte etc...)


    Beim Programmstart fülle ich eine Collection(Of EQ_Component) mit einer vielzahl von Instanzen dieses Objekts aus denen der User welche auswählen kann.
    Ich habe ein TabControl und auf jedem TabControl befindet sich ein DataGridview das an eine BindingList(Of EQ_Component) gebunden ist. Wählt der User Componenten aus, so landen diese in der BindingList und werden im DataGridView angezeigt.
    Es gibt die Funktion mit welcher der Anwender eine EQ_Component von einer BindingList in eine andere BindingList zu kopieren kann. Mir ist nun aufgefallen, dass sobald er dies tut, die ChangeEvents in der QuellListe ausgelöst werden und nicht in der Liste in der er das Objekt kopiert hat.
    Die Lösung war, beim Ausführen von Clone() den PropertyChanged Delegaten in der Kopie auf Nothing zu setzten. Es scheint zu funktionieren, aber ich bin mir nicht sicher ob das der Richtige weg ist. Scheint mir mehr ein Workaround zu sein. Vielleicht kennt ihr einen besseren Weg?
    "Es ist absolut möglich, dass jenseits der Wahrnehmung unserer Sinne ungeahnte Welten verborgen sind." — Albert Einstein
    "Wenn die Macht der Liebe die Liebe zur Macht übersteigt, erst dann wird die Welt endlich wissen, was Frieden heißt." — Jimi Hendrix

    @FredM:: Du kannst auch eine Boolean Property setzen, die den Zustand beschreibt und die Du zum Event-Raisen oder nicht auswertest.
    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!
    Das meinte ich nicht.

    Beispiel:

    BindingList1
    - Komponente 1
    - Komponente 2
    - Komponente 3

    BindingList2
    - Komponente 4
    - Komponente 5
    - Komponente 6

    Man Kopiere nun Komponente 2 in BindingList2

    BindingList1
    - Komponente 1
    - Komponente 2
    - Komponente 3

    BindingList2
    - Komponente 4
    - Komponente 5
    - Komponente 6
    - Komponente 2 (copy)

    Führe ich nun eine Änderung an Komponente 2 (copy) durch z.B. Ändere den ItemName wird nun in BindingList1 das ListChanged Event ausgelöst obwohl sich die Komponente ja in BindingList2 befindet.
    "Es ist absolut möglich, dass jenseits der Wahrnehmung unserer Sinne ungeahnte Welten verborgen sind." — Albert Einstein
    "Wenn die Macht der Liebe die Liebe zur Macht übersteigt, erst dann wird die Welt endlich wissen, was Frieden heißt." — Jimi Hendrix

    Stimmt nicht ganz was ich gerade erzählt hab, ist vor dem Kopieren der InvocationCount = 1 ist nach dem kopieren und einfügen in die neue Liste der InvocationCount=2
    Auf der InvocationList befindet sich jetzt sowohl die BindingList1 als auch die BindingList2

    Statt den EventDelegaten auf Nothing zu setzten, müsste ich korrekterweise das eine Element aus der InvocationList entfernen, aber wie komm ich an die ran?
    Bilder
    • invocCount.png

      23,82 kB, 1.058×192, 147 mal angesehen
    "Es ist absolut möglich, dass jenseits der Wahrnehmung unserer Sinne ungeahnte Welten verborgen sind." — Albert Einstein
    "Wenn die Macht der Liebe die Liebe zur Macht übersteigt, erst dann wird die Welt endlich wissen, was Frieden heißt." — Jimi Hendrix

    Was löst denn

    FredM schrieb:

    das ListChanged Event aus
    :?:
    Das Anstoßen des Clonens oder das Anhängen an eine Liste?
    Vielleicht solltest Du

    VB.NET-Quellcode

    1. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(EQ_Tools.GetMemberName(Function() Me.ItemName)))
    nur dann aufrufen, wenn sich der Name geändert hat, also mit einem If drum herum.
    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!
    @Rod das hat aber nichts mit dem Problem der zwei Listen zu tun.

    Habe es jetzt so gelöst. Denke das ist sauber.

    VB.NET-Quellcode

    1. Public Function Clone() As Object Implements System.ICloneable.Clone
    2. Dim copy As EQ_Component = Me.MemberwiseClone()
    3. copy.RemoveDelegates()
    4. Return copy
    5. End Function
    6. Protected Sub RemoveDelegates()
    7. 'PropertyChangedEvent = Nothing
    8. If Not IsNothing(PropertyChangedEvent) Then
    9. Dim Delegates() As System.Delegate = PropertyChangedEvent.GetInvocationList
    10. If Delegates.Length > 0 Then
    11. For Each del In Delegates
    12. RemoveHandler Me.PropertyChanged, del
    13. Next
    14. End If
    15. End If
    16. End Sub


    Hier gibt es ein guten Artikel dazu: informit.com/articles/article.aspx?p=25848&seqNum=6
    Auch hilfreich: codeproject.com/Messages/27720…t-of-a-static-event-.aspx
    "Es ist absolut möglich, dass jenseits der Wahrnehmung unserer Sinne ungeahnte Welten verborgen sind." — Albert Einstein
    "Wenn die Macht der Liebe die Liebe zur Macht übersteigt, erst dann wird die Welt endlich wissen, was Frieden heißt." — Jimi Hendrix

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

    ich glaub, das einfache

    VB.NET-Quellcode

    1. PropertyChangedEvent=Nothing
    hat dieselbe Wirkung wie das komplizierte

    VB.NET-Quellcode

    1. If Not IsNothing(PropertyChangedEvent) Then
    2. Dim Delegates() As System.Delegate = PropertyChangedEvent.GetInvocationList
    3. If Delegates.Length > 0 Then
    4. For Each del In Delegates
    5. RemoveHandler Me.PropertyChanged, del
    6. Next
    7. End If
    8. End If


    Das einzige was mich wundert ist, wo PropertyChangedEvent eiglich herkommt, und Welchen Datentyp hat das Objekt?