Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

INotifyPropertyChanged - Απορία

Îåêßíçóå áðü ôï ìÝëïò cap. Τελευταία δημοσίευση από το μέλος PALLADIN στις 30-01-2007, 22:33. Υπάρχουν 12 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  30-01-2007, 13:07 24262

    INotifyPropertyChanged - Απορία

    Σενάριο:

    Εχω ένα business object με 5-6 properties (counters κυρίως) τους οποίους έχω δέσει με simple binding (mycontrol.databindings.add("text", myBusinessObject, "MyPropertyName") σε ορισμένα labels μιας φόρμας.

    Τα συγκεκριμένα properties είναι read-only και αλλάζουν εσωτερικά από το ίδιο των business object το οποίο "πειράζει" όταν τρέχουν κάποιες methods του τα property backer variables. Οκ μεχρι εδώ, για να "βλέπουν" λοιπόν τα bound control τις αλλαγές χρειάζεται να υλοποιηθεί το INotifyPropertyChanged, όπως και έκανα.

    Παρατήρησα όμως κάτι αξιον αναφοράς: Λογω του οτι στο ίδιο instance του business object έχω bound 5-6 properties σε αντίστοιχα labels της φόρμας μου, αρκεί να κάνω raiseEvent για ΕΝΑ από αυτά και ενημερώνονται οι τιμές και των 6 στη φόρμα! Δηλαδή, όταν σηκώνω το Event PropertyChanged είναι σαν να μην τον ενδιαφέρει το συγκεκριμένο property αλλά να κάνει update τα bindings όλων των properties που βρίσκονται bound στο συγκεκριμένο instance!

    Κουλό, ή behaviour by design; Και αν by design, μήπως ξέρει κανείς το γιατί;


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
    Δημοσίευση στην κατηγορία: , ,
  •  30-01-2007, 14:52 24270 σε απάντηση της 24262

    Απ:INotifyPropertyChanged - Απορία

    Γενικά το INotifyPropertyChanged είναι ένα πολύ απλό interface με τo PropertyChanged να περιέχει ως EventArg το όνομα του property που έχει αλλάξει. That's all. Από εκεί και πέρα αυτό που περιγράφεις (όχι ότι έχω τίποτα πληροφορίες εκ των έσω) μάλλον είναι by design. Για να πω την αλήθεια μου φαίνεται πολύ φυσιολογική αυτή η συμπεριφορά. Αν υποθέσουμε ότι έχουμε ένα binded object που μέσω κάποιου method αλλάζουν μερικά properties, δεν θα ήταν πολύ incosistent να δεις να αλλάζει η τιμή σε μερικά από αυτά τα properties ενώ στα υπόλοιπα άλλη τιμή θα δείχνει το control και άλλη θα έχει το property; Δεν θα έχεις εσφαλμένη εντύπωση για την τιμή των υπολοίπων; Ίσως στο business μοντέλο σου να έχει λογική κάτι τέτοιο ωστόσο μου φαίνεται φυσιολογικός αυτός ο τρόπος λειτουργίας...


    Vir prudens non contra ventum mingit
  •  30-01-2007, 15:11 24272 σε απάντηση της 24270

    Απ:INotifyPropertyChanged - Απορία

    Αν το PropertyChanged event προκαλείται κάθε φορά που αλλάζει η τιμή οποιυδήποτε property που συμμετέχει σε binding, τότε η συμπεριφορά αυτή δεν έχει να προσφέρει κάτι. Αντίθετα, ενημερώνει τα controls πολλαπλές φορές σε συνεχόμενες αλλαγές διαφορετικών properties.

    Νατάσα Μανουσοπούλου
  •  30-01-2007, 15:19 24273 σε απάντηση της 24262

    Απ:INotifyPropertyChanged - Απορία

    Το δοκίμασα και το ίδιο συμβαίνει αν παίξεις με τον τρόπο που υποστηρίζεται στο Framework 1.1. Δηλαδή για κάθε property που αλλάζει να διαθέτεις κι από ένα event που κατά σύμβαση έχει όνομα <propertyname>Changed και να το ενεργοποιείς στο set του property.

     


    Vir prudens non contra ventum mingit
  •  30-01-2007, 16:05 24274 σε απάντηση της 24272

    Απ:INotifyPropertyChanged - Απορία

    Νατάσα Μανουσοπούλου:
    Αν το PropertyChanged event προκαλείται κάθε φορά που αλλάζει η τιμή οποιυδήποτε property που συμμετέχει σε binding, τότε η συμπεριφορά αυτή δεν έχει να προσφέρει κάτι. Αντίθετα, ενημερώνει τα controls πολλαπλές φορές σε συνεχόμενες αλλαγές διαφορετικών properties.

    Αυτό ακριβώς ήταν που μου έκανε εντύπωση. Φαντάσου να έχω ένα business object με 1000 properties (λέμε τώρα) bound σε αντίστοιχα 1000 controls μιας μεγαααααλης φόρμας (και πάλι λέμε τώρα) και να αλλάξει ΕΝΑ property. Θα γίνουν update και τα 1000!

     


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  30-01-2007, 16:29 24278 σε απάντηση της 24274

    Απ:INotifyPropertyChanged - Απορία

    cap:

    Αυτό ακριβώς ήταν που μου έκανε εντύπωση. Φαντάσου να έχω ένα business object με 1000 properties (λέμε τώρα) bound σε αντίστοιχα 1000 controls μιας μεγαααααλης φόρμας (και πάλι λέμε τώρα) και να αλλάξει ΕΝΑ property. Θα γίνουν update και τα 1000!

    Είναι by design προειδοποίηση για code smell τύπου Gob object Smile


    Palladinos Nick
    Software Engineer
    -----------------------
    The limits of my language mean the limits of my world. (Ludwig Wittgenstein)
  •  30-01-2007, 16:36 24279 σε απάντηση της 24278

    Απ:INotifyPropertyChanged - Απορία

    (Ξυνει κεφάλι απορημένος) Τιντούτ;
    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  30-01-2007, 16:43 24280 σε απάντηση της 24279

    Απ:INotifyPropertyChanged - Απορία

    Ηθελα να πω ότι η MS αποφάσισε να έχει αυτή την συμεριφορά για να αποφεύγονται αντικείμενα με 1000 properties... To post ειχε χιουμοριστική διάθεσηStick out tongue


    Palladinos Nick
    Software Engineer
    -----------------------
    The limits of my language mean the limits of my world. (Ludwig Wittgenstein)
  •  30-01-2007, 16:46 24281 σε απάντηση της 24274

    Απ:INotifyPropertyChanged - Απορία

    cap:

    Νατάσα Μανουσοπούλου:
    Αν το PropertyChanged event προκαλείται κάθε φορά που αλλάζει η τιμή οποιυδήποτε property που συμμετέχει σε binding, τότε η συμπεριφορά αυτή δεν έχει να προσφέρει κάτι. Αντίθετα, ενημερώνει τα controls πολλαπλές φορές σε συνεχόμενες αλλαγές διαφορετικών properties.

    Αυτό ακριβώς ήταν που μου έκανε εντύπωση. Φαντάσου να έχω ένα business object με 1000 properties (λέμε τώρα) bound σε αντίστοιχα 1000 controls μιας μεγαααααλης φόρμας (και πάλι λέμε τώρα) και να αλλάξει ΕΝΑ property. Θα γίνουν update και τα 1000!

     

    Είναι αναπόφευκτο ωστόσο, όταν δεν ξέρεις ποιό από τα 1000 properties θα αλλάξει. Αν ξέρεις, βάζεις το PropeprtyChanged μόνο στο property που σε ενδιαφέρει. Από την άλλη, μπορείς να αποφύγεις έναν τέτοιο σενάριο υλοποιώντας τον κατάλληλο μηχανισμό. Πρόσεξε: Ο designer όταν σχεδιάζει τη φόρμα βάζει στην αρχή Me.SuspendLayout και αφού τοποθετήσει όλα τα controls, στο τέλος Me.ResumeLayout(False) ώστε να αποφύγει τον τμηματικό σχεδιασμό της φόρμας. Το ίδιο κάνει και το DataRow object όπου με DataRow.BeginEdit κάνεις suspend την ενεργοποίηση των events που προκύπτουν από τα validation rules και στο τέλος με DataRow.ΕndEdit κάνεις ένα συνολικό validate. Αντίστοιχα κι εσύ μπορείς να φτιάξεις ένα ζευγάρι Begin/End ή Suspend/Resume για τη business κλάση σου. Πχ:

    Imports System.ComponentModel

    Public Class Customer
        Implements INotifyPropertyChanged

        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

        Private _CustomerID As String
        Private _CustomerName As String

        Private notificationSuspended As Boolean = False

        Public Property CustomerID() As String
            Get
                Return _CustomerID
            End Get
            Set(ByVal value As String)
                _CustomerID = value
                RaisePropertyChanged("CustomerID")
            End Set
        End Property

        Public Property CustomerName() As String
            Get
                Return _CustomerName
            End Get
            Set(ByVal value As String)
                _CustomerName = value
                RaisePropertyChanged("CustomerName")
            End Set
        End Property

        Public Sub SuspendNotification()
            notificationSuspended = True
        End Sub

        Public Sub ResumeNotification(ByVal notifyChanges As Boolean)
            notificationSuspended = False
            If notifyChanges Then
                RaisePropertyChanged(String.Empty)
            End If
        End Sub

        Private Sub RaisePropertyChanged(ByVal propertyName As String)
            If Not notificationSuspended Then
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
            End If
        End Sub
    End Class

    Έτσι, αν πεις

            x.CustomerID = "a"
            x.CustomerName = "b"

    τρέχουν δύο events. Αν πεις

            x.SuspendNotification()

            x.CustomerID &= "2"
            x.CustomerName &= "2"

            x.ResumeNotification(True)

    τρέχει ένα event. Και αν πεις

            x.SuspendNotification()

            x.CustomerID &= "3"
            x.CustomerName &= "3"

            x.ResumeNotification(False)

    δεν τρέχει κανένα event.

    Happy?


    Vir prudens non contra ventum mingit
  •  30-01-2007, 16:50 24282 σε απάντηση της 24281

    Απ:INotifyPropertyChanged - Απορία

    Μανο, αυτό που παραθέτεις είναι σωστό. Μονο που:

    Εστω οτι εγώ έχω n bound properties ενός business object και σηκώνω ΜΟΝΟ για ένα το PropertyChanged Event. Βλέπω όμως στη φόρμα, παρόλο που σήκωσα propertyChanged event για το συγκεκριμένο property, να ενημερώνονται ΟΛΕΣ οι τιμές (αυτό που έλεγα στην αρχή). Ενα event δεν έχει τρέξει; Αυτό που έκανα raise;

     


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  30-01-2007, 17:01 24283 σε απάντηση της 24282

    Απ:INotifyPropertyChanged - Απορία

    Μάλλον δεν συνενοηθήκαμε. Αυτό το θέμα δεν το καλύψαμε; O binding manager κάνει refresh όλα τα controls που είναι binded πάνω στο object σου. Δε νομίζω να μπορείς να κάνεις κάτι γι αυτό. Η Νατάσα όμως είπε

    Νατάσα Μανουσοπούλου:
    Αν το PropertyChanged event προκαλείται κάθε φορά που αλλάζει η τιμή οποιυδήποτε property που συμμετέχει σε binding, τότε η συμπεριφορά αυτή δεν έχει να προσφέρει κάτι. Αντίθετα, ενημερώνει τα controls πολλαπλές φορές σε συνεχόμενες αλλαγές διαφορετικών properties.

    Ως προς αυτό, για να γλυτώσεις τα 1000 raise events, κάνεις αυτό που έγραψα με το suspend/resume. Μου φαίνεται πολύ μεγαλύτερο το overhead που προκαλείται από 1000 raiseevents παρά από το refresh 1000 controls.

    Edit: Όπου 1000 raise events επί 1000 control refreshes = 100000 control refreshes μιας και κάθε raise event θα προκαλεί 1000 refresh


    Vir prudens non contra ventum mingit
  •  30-01-2007, 20:17 24297 σε απάντηση της 24283

    Απ:INotifyPropertyChanged - Απορία

    Ναι, έχεις δίκιο Μανο. Μπερδεύτηκα εγώ.

    Οκ, σωστά! Αρα λοιπόν αν δεν ενδιαφέρεται κάποιος για άλλα πράγματα παρά μόνο για το refresh των bound controls του, αρκεί να σηκώσει ΕΝΑ event για να γίνουν refresh ΟΛΑ τα controls που βρίσκονται bound επάνω στο συγκεκριμένο instance. Τι propertyChanged για κάθε property και αηδίες...:)

    Γκρουμφ. Χρήσιμος ο κώδικάς σου, αλλά κακή ως κάκιστη η υλοποίηση του binding σε αυτο το σημείο. Τουλάχιστον θα μπορούσε να έχει ένα BindingManager.Refresh(myInstance). (Η εχει; ;) )

    Κλείνω το θέμα, ευχαριστώ για τις απαντήσεις. Κυριε Palladin (ξέρεις οτι το όνομά σου είναι και race στο WoW ε; :) , ακόμα δεν μου εξηγήσατε τι σημαίνει GOB Object και θα μείνω με την απορία :)

     

     

     

     


    Σωτήρης Φιλιππίδης

    DotSee Web Services

    View Sotiris Filippidis's profile on LinkedIn

    DotNetNuke them!
  •  30-01-2007, 22:33 24299 σε απάντηση της 24297

    Απ:INotifyPropertyChanged - Απορία

    cap:
    ακόμα δεν μου εξηγήσατε τι σημαίνει GOB Object και θα μείνω με την απορία :)

    Oups Sorry Σωτήρη εννοούσα God object....

    cap:
    ξέρεις οτι το όνομά σου είναι και race στο WoW ε; :)

    Ναι το ξέρω, είναι ένα πολύ ιδιαίτερο race... Υπήρχαν και στο παλιό real time strategy Warcraft.

    Πάντως για την ιστορία, το Palladin προέρχεται απο το επίθετό μου => Παλλαδινός


    Palladinos Nick
    Software Engineer
    -----------------------
    The limits of my language mean the limits of my world. (Ludwig Wittgenstein)
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems