INotifyPropertyChanged Question.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • babai28
    New Member
    • Jul 2008
    • 59

    INotifyPropertyChanged Question.

    I was really excited when I learned the usage of INotifyProperty Changed interface. It made binding a bliss and the UI highly interactive and dynamic for me. But then with every problem comes a solution and more problems.
    I will explain my question with an example. I have a student class.
    Code:
    public class Student : INotifyPropertyChanged
    {       
            const int MINIMUM_AGE = 1;
            int rollNumber = 0;
            int age = 0;
            string studentName = string.Empty;
            
            #region INotifyPropertyChanged Members
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion
         
            public Student() { }
            public Student(string studentName, int age, int rollNumber)
            {           
                this.StudentName = studentName;
                this.StudentAge = age;
                this.RollNumber = rollNumber;
            }
            
            public string Name
            {
                get
                {
                    return this.studentName;
                }
                set
                {
                    if (value != this.studentName)//guard clause
                    {
                        if (value.Trim() == string.Empty)
                            throw new Exception("Name assigned does not confirms to the format. Please assign a proper alphanumeric value.");
                        this.studentName = value;
                        this.DisplayPropertyChange("StudentName");
                    }
                }
            }
    
            public int StudentAge
            {
                get
                {
                    return this.age;
                }
                set
                {
                    if (value != this.age)//guard clause
                    {
                        //any value lesss than minumum age goes to minimum ages.
                        if (value < MINIMUM_AGE)
                            this.age = MINIMUM_AGE;                                   
                        else
                            this.age = value;
                         this.DisplayPropertyChange("StudentAge");
                    }
                }
            }
    
            public int RollNumber
            {
                get
                {
                    return this.rollNumber;
                }
                set
                {
                    if (value != this.rollNumber)//guard clause
                    {
                        if (value < 0)
                            throw new Exception("Wrong value supplied. Only non negative integers allowed.");
                        this.rollNumber = value;
                        this.DisplayPropertyChange("RollNumber");
                       
                    }
                }
            }
    
            void DisplayPropertyChange(string propertyName)
            {
                if (null!=this.PropertyChanged)
                {
                    this.PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
                }
            }        
    }
    So far so good. Binding to any of the property would reflect the change in the binded object.
    Now, in the same class a property type is a complex/user defined type. Then how are we going to handle it.?e.g.
    say in the above class the Name property is changed to the following class instead of string:

    Code:
    public class StudentName
    {
            string firstName = string.Empty;
            string lastName = string.Empty;
    
            public string FirstName
            {
                get { return firstName; }
                set { firstName = value; }
            }
            public string LastName
            {
                get { return lastName; }
                set { lastName = value; }
            }
    
            public string FullName
            {
                get { return String.Concat(this.firstName," ",this.lastName); }
            }
            //Default
            public StudentName()
            {}
            //Overloaded
            public StudentName(string firstName, string lastName)
            {
                this.firstName = firstName;
                this.lastName = lastName;
            }
    }
    And I would access it with something like:
    Code:
    Student student=new Student();
    string.Format("The student's name is {0}",student.Name.FullName);
    I implemented the INotifyProperty Changed interface in the class StudentName too. But the change is still not getting reflected automatically.
    IF INotifyPorperty Changed is not extendable for complex property is there some workaround?
    Or am I overlooking some Object Oriented Concept here?
    Any help will be highly appreciated.

    Regards,
    Sid
  • ThatThatGuy
    Recognized Expert Contributor
    • Jul 2009
    • 453

    #2
    Originally posted by babai28
    Hi Experts,

    I was really excited when I learned the usage of INotifyProperty Changed interface. It made binding a bliss and the UI highly interactive and dynamic for me. But then with every problem comes a solution and more problems.
    I will explain my question with an example. I have a student class.
    Code:
    public class Student : INotifyPropertyChanged
    {       
            const int MINIMUM_AGE = 1;
            int rollNumber = 0;
            int age = 0;
            string studentName = string.Empty;
            
            #region INotifyPropertyChanged Members
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion
         
            public Student() { }
            public Student(string studentName, int age, int rollNumber)
            {           
                this.StudentName = studentName;
                this.StudentAge = age;
                this.RollNumber = rollNumber;
            }
            
            public string Name
            {
                get
                {
                    return this.studentName;
                }
                set
                {
                    if (value != this.studentName)//guard clause
                    {
                        if (value.Trim() == string.Empty)
                            throw new Exception("Name assigned does not confirms to the format. Please assign a proper alphanumeric value.");
                        this.studentName = value;
                        this.DisplayPropertyChange("StudentName");
                    }
                }
            }
    
            public int StudentAge
            {
                get
                {
                    return this.age;
                }
                set
                {
                    if (value != this.age)//guard clause
                    {
                        //any value lesss than minumum age goes to minimum ages.
                        if (value < MINIMUM_AGE)
                            this.age = MINIMUM_AGE;                                   
                        else
                            this.age = value;
                         this.DisplayPropertyChange("StudentAge");
                    }
                }
            }
    
            public int RollNumber
            {
                get
                {
                    return this.rollNumber;
                }
                set
                {
                    if (value != this.rollNumber)//guard clause
                    {
                        if (value < 0)
                            throw new Exception("Wrong value supplied. Only non negative integers allowed.");
                        this.rollNumber = value;
                        this.DisplayPropertyChange("RollNumber");
                       
                    }
                }
            }
    
            void DisplayPropertyChange(string propertyName)
            {
                if (null!=this.PropertyChanged)
                {
                    this.PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
                }
            }        
    }
    So far so good. Binding to any of the property would reflect the change in the binded object.
    Now, in the same class a property type is a complex/user defined type. Then how are we going to handle it.?e.g.
    say in the above class the Name property is changed to the following class instead of string:

    Code:
    public class StudentName
    {
            string firstName = string.Empty;
            string lastName = string.Empty;
    
            public string FirstName
            {
                get { return firstName; }
                set { firstName = value; }
            }
            public string LastName
            {
                get { return lastName; }
                set { lastName = value; }
            }
    
            public string FullName
            {
                get { return String.Concat(this.firstName," ",this.lastName); }
            }
            //Default
            public StudentName()
            {}
            //Overloaded
            public StudentName(string firstName, string lastName)
            {
                this.firstName = firstName;
                this.lastName = lastName;
            }
    }
    And I would access it with something like:
    Code:
    Student student=new Student();
    string.Format("The student's name is {0}",student.Name.FullName);
    I implemented the INotifyProperty Changed interface in the class StudentName too. But the change is still not getting reflected automatically.
    IF INotifyPorperty Changed is not extendable for complex property is there some workaround?
    Or am I overlooking some Object Oriented Concept here?
    Any help will be highly appreciated.

    Regards,
    Sid
    You need to assign a method to the delegate of the PropertyChanged event...

    something like this...
    Code:
    student.PropertyChanged+=new PropertyChangedEventHandler(student_PropertyChanged);
    and write the code to effect in that method

    Comment

    • Christian Binder
      Recognized Expert New Member
      • Jan 2008
      • 218

      #3
      I don't know, if I understood your question correct, but I think you ment you won't be notified if a property of your property changes.?

      E.g.
      Code:
      Student s = new Student();
      s.PropertyChanged += x;
      void x(...) {
        //handle change
      }
      
      s.Age = 99; // now x() would be called
      s.Name = new StudentName("John", "Doe"); // x() would be called
      s.Name.FirstName = "Jane"; // x() WON'T be called
      Is this your problem?
      If yes, then you could solve it this way:

      Student is IPropertyChange d, StudentName is IPropertyChange d too!

      Code:
      // in class student
      public StudentName StudentName {
        get{
        // ...
        }
      
        set {
         //detach from relayed event
         _studentName.PropertyChanged -= RelayPropertyChange;
      
          _studentName = value;
          OnNotifyPropertyChanged("StudentName");
      
          //If any changes are made in object of StudentName, RelayPropertyChange will be called
          _studentName.PropertyChanged += RelayPropertyChange;
        }
      }
      
      void RelayPropertyChange(...) {
        // here you can raise anoter propertychanged-event (of property "Name")
      }

      Comment

      • ThatThatGuy
        Recognized Expert Contributor
        • Jul 2009
        • 453

        #4
        Originally posted by ChBinder
        I don't know, if I understood your question correct, but I think you ment you won't be notified if a property of your property changes.?

        E.g.
        Code:
        Student s = new Student();
        s.PropertyChanged += x;
        void x(...) {
          //handle change
        }
        
        s.Age = 99; // now x() would be called
        s.Name = new StudentName("John", "Doe"); // x() would be called
        s.Name.FirstName = "Jane"; // x() WON'T be called
        Is this your problem?
        If yes, then you could solve it this way:

        Student is IPropertyChange d, StudentName is IPropertyChange d too!

        Code:
        // in class student
        public StudentName StudentName {
          get{
          // ...
          }
        
          set {
           //detach from relayed event
           _studentName.PropertyChanged -= RelayPropertyChange;
        
            _studentName = value;
            OnNotifyPropertyChanged("StudentName");
        
            //If any changes are made in object of StudentName, RelayPropertyChange will be called
            _studentName.PropertyChanged += RelayPropertyChange;
          }
        }
        
        void RelayPropertyChange(...) {
          // here you can raise anoter propertychanged-event (of property "Name")
        }
        ya it doesnt change automatically like that....
        you need to write code for it

        Comment

        Working...