Änderung eines Propertys im Code überwachen

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von SKeks.

    Änderung eines Propertys im Code überwachen

    Hallo Leute,

    leider hab ich schon wieder ein Problem.
    Im Code-Behind eines WPF-Programms ist ein Property vom Typ ObservableCollection(of...) angelegt. Das Prgramm soll reagieren, wenn sich ein bestimmtes Property in der Collection verändert. Get und Set des Property vom Typ ObservableCollection(of...) werden bei einer Änderung aber nicht durchlaufen, sondern nur wenn der Collection etwas hinzugefügt oder gelöscht wird. In der zugewiesenen Klasse wird die Änderung des Propertys erkannt.
    Leider habe ich keine Ahnung, wie man nun über ein Event in der Klasse den Code-Behind benachrichtigt, bzw. sogar übergibt welches Property an welchem Index sich geändert hat.
    Die Collection:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private _timer_coll As ObservableCollection(Of Timer_Klasse)
    2. Public Property Timer_Coll() As ObservableCollection(Of Timer_Klasse)
    3. Get
    4. Return _timer_coll
    5. End Get
    6. Set(ByVal value As ObservableCollection(Of Timer_Klasse))
    7. _timer_coll = value
    8. raisepropertychanged()
    9. End Set
    10. End Property


    die Timer_Klasse (Ausschnitt)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Implements INotifyPropertyChanged 'benachrichtigt die Oberfläche (View) bei Änderung eines Propertys
    2. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    3. Private Sub raisepropertychanged(<CallerMemberName> Optional ByVal prop As String = "") 'wird bei Änderung in den Propertys aufgerufen
    4. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
    5. End Sub
    6. Public Event werwars_event()
    7. Private Sub werwars(<CallerLineNumber> Optional ByVal index As Integer = 0) 'wird bei Änderung in den Propertys aufgerufen
    8. RaiseEvent werwars_event()
    9. End Sub
    10. Private _vorlaufzeit As Long
    11. Public Property Vorlaufzeit As Long
    12. Get
    13. Return _vorlaufzeit
    14. End Get
    15. Set(value As Long)
    16. _vorlaufzeit = value
    17. raisepropertychanged() 'der Oberfläche wird die Änderung des Property mitgeteilt
    18. werwars()
    19. End Set
    20. End Property


    Code_behind:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Property Test As Timer_Klasse
    2. Sub testevent()
    3. Console.WriteLine("event")
    4. End Sub
    5. 'folgendes steht in der Window_loaded Sub:
    6. Test = New Timer_Klasse
    7. AddHandler Test.werwars_event, AddressOf testevent


    Leider klappt das nicht. Das Event wird im Code-Behind nicht ausgelöst. In der Klasse wirds aber gefeuert.
    Ich befürchte, dass ich da mal wieder komplett auf dem Holzweg bin... :(

    P.S. die ObservableCollection ist noch mit einer ICollectionView verbunden, falls das vielleicht etwas zur Lösung beitragen kann.

    Gruß

    eddi
    Hallo

    eichseinet schrieb:

    Get und Set des Property vom Typ ObservableCollection(of...) werden bei einer Änderung aber nicht durchlaufen, sondern nur wenn der Collection etwas hinzugefügt oder gelöscht wird.

    Eigentlich nicht. Nur wenn die Collection neu erstellt wird. Also dem Property eine neuer Wert gesetzt wird. Beim löschen oder hinzufügen wird der Setter auch nicht durchlaufen. Hierfür gibt es das Event CollectionChanged.

    Aber nun zu deinem Eigendlcihen problem. Bevor ich kompliziertere Wege einschlage wäre interessant genau zu definieren was mit "Das Prgramm soll reagieren, wenn sich ein bestimmtes Property in der Collection verändert" genau gemeint ist und vorallem WO darauf reagiert werden soll. Innerhalb der jeweiligen Klasseninstanz wo dies passiert oder ausserhalb.

    Ich denke es wäre in diesem Fall gut mal zu beschreiben was das ding machen soll, bzw. was das wird.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Bei so viel Neuem hab ich einfach den Wald vor Bäumen nicht mehr gesehen! Ich war so konzentriert die Position aus der Collection zu holen, dass ich ganz die Events vom DataGrid vergessen hab. :)
    Über das Events "BeginningEdit" holt das Prgramm jetzt wie folgt die Position:

    VB.NET-Quellcode

    1. Console.WriteLine(Timer_DataGrid.CurrentColumn.Header) 'hab extra den Header, statt des Index genommen, passt dann auch noch wenn Spalten dazu kommen oder wegfallen
    2. Console.WriteLine(Timer_View.CurrentPosition.ToString) 'das ICollectionView


    Das Event "CellEditEnding" startet dann den Schreibvorgang in die andere Collection.
    So löst sich auch gleichzeit das Problem zu unterscheiden, ob eine manuelle Änderung stattfand, oder ob aus dem Code heraus ein Property geändert wurde.

    Der Text unten ist damit eigentlich hinfällig. Ich lass ihn nur mal, falls es doch irgendjemanden interessiert. Mein Problem ist damit gelöst.

    Danke, dass Du mal wieder zur Hilfe bereit warst.

    Gruß

    eddi



    ursprünglicher Beitrag: unwichtig und nur noch bie Interesse

    Oha. Beschreiben was da passieren soll, na das wird lustig.

    Erst mal gibt es da 2 Klassen mit Daten. Timer_Klasse und Timer_einzeln_Klasse.
    Von beiden Klassen wird je eine Properperty als ObservableCollection im Code-Behind erstellt.
    Timer_einzeln_Klasse (also die Collection) wird von einem externen Programm mit Daten gefüttert, indem mein Programm eine XML einliest, wenn sie vom FileSystemWatcher erkannt wird. Diese Klasse enthält alle Daten zu einer TV-Sendung (und diese sollen dauerhaft erhalten bleiben). Jeder neue Eintrag enthält die Daten zu EINER TV-Sendung. Wenn eine neue Sendung dazu kam, dann prüft mein Programm, ob diese mit einer anderen kombiniert werden muss. (z.B. Sendung von 20:15-21:15 existiert schon, Sendung von 21:15 bis 22:15 kommt neu dazu, dann muss eine Aufnahme von 20:15 bis 22:15 plus 10min früher und 10min. länger programmiert werden)
    Timer_Klasse enthält dann die fertig zusammengesetzten Sendungen und nur noch einen Teil der Daten.
    Beide Klassen werden je in einem eigenen DataGrid angezeigt. Beide werden benötigt.
    Im DataGrid von Timer_klasse (also die zusammengesetzten Aufnahmen) soll jetzt die Zeit aber manuell änderbar sein, die vor dem Termin in der TV-Zeitschrift aufgenommen wird (die Zeiten passen ja nie wirklich). Die Zeit wurde aus der anderen Klasse fertig übernommen. Weil die Timer_einzeln_Klasse aber meine Datenbasis darstellt, muss die Änderung dorthin zurück übertragen werden.

    Im Anhang mal ein Bild zur Verdeutlichung, aber nur mit den wichtigsten Daten.

    Nachtrag: Luxus wäre es, wenn das Programm mir meldet an welchem Index der Collection und an welchem Property sich etwas geändert hat. Dann kann ich gezielt die Daten zurück schreiben. (der Index in der ursprünglichen Klasse / Collection ist hinterlegt und daher bekannt)

    Schön wärs, wenn man man mir mitteilt, welches Property sich geändert hat. Dann schreib ich halt alle Zeiten zurück oder vergleiche vorher auf Unterschiede.

    Minimum muss ich wissen, dass sich irgendein Property geändert hat. Dann muss ich halt alle relevanten Daten vergleichen und zurück schreiben.

    Natürlich könnte man zum DataGrid von Timer_einzeln_Klasse wechseln und ort die Zeit ändern. Das müüst dann aber u.U. bei mehreren Einzelsendungen zu einer Aufnahme passieren. Die geänderte Zeit soll halt auch erhalten bleiben, wenn eine der Teilsendungen wieder entfernt wird.
    Komfort follows einfachem Programm. :) :D

    GRuß

    eddi
    Bilder
    • Timer.PNG

      90,33 kB, 1.225×410, 91 mal angesehen

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „eichseinet“ ()

    Wenn die Objekte in der ObservableCollection(of TestObject) auch INotifyPropertyChanged implementieren kannst du das PropertyChanged Event der Objekte abbonnieren.

    Mehr oder weniger so:

    VB.NET-Quellcode

    1. AddHandler TestObject.PropertyChanged, AddressOf DoSomething
    2. Protected Sub DoSomething(sender As Object, e As PropertyChangedEventArgs)
    3. If e.PropertyName = "TestProperty" Then
    4. DoAnythingElse
    5. End If
    6. End Sub


    Die If-Abfrage kann auch weggelassen werden wenn nur Änderungen an sich gewünscht sind. Bestimmt gibt es auch Möglichkeiten nicht mit nem Zauber-String zu arbeiten, denn falls sich der Name der Eigenschaft ändern sollte muss nämlich auch dieser String verändert werden.

    Edit:

    Hab ich gerade gefunden mit

    VB.NET-Quellcode

    1. dim str = NameOf(TestObject.TestProperty)


    bekommt man den Propertyname als String zurück für die If-Abfrage. so dass auch Eigenschaftennamensänderungen abgefangen werden ohne Zauberstring

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