Question Problem with notify on property change

FlashOwl

Member
Joined
Jul 15, 2011
Messages
9
Programming Experience
10+
This relates to vb.net on vs2008

I have a form (in actual fact many forms) in which the fields are bound to the public properties of class I have created. For example let say it is a customer class object oCustomer of type clsCustomer.

In the Set section of property declaration I use the NotifyPropertyChanged("propertyname") command like this:-
VB.NET:
Public Class clsCustomer
    Implements INotifyPropertyChanged

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

    Private m_NotifyOnPropertyChange As Boolean = True
    Private mAddress4 as string = ""

   Public Overridable Property Address4() As String
      Get
         Return mAddress4
      End Get
      Set(ByVal Value As String)
         If mAddress4 <> Value Then
            mAddress4 = Value
            [B]NotifyPropertyChanged("Address4")[/B]
         End If
      End Set
   End Property[/SIZE]
[SIZE=2]
[/SIZE][SIZE=2]	Public Property _NotifyOnPropertyChange() As Boolean[/SIZE]
[SIZE=2]        Get[/SIZE]
[SIZE=2]            Return m_NotifyOnPropertyChange[/SIZE]
[SIZE=2]        End Get[/SIZE]
[SIZE=2]        Set(ByVal value As Boolean)[/SIZE]
[SIZE=2]            m_NotifyOnPropertyChange = value[/SIZE]
[SIZE=2]        End Set[/SIZE]
[SIZE=2]    End Property

	Public Sub NotifyPropertyChanged(ByVal PropertyName As String)
        If Me.m_NotifyOnPropertyChange Then
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
        End If
    End Sub

[/SIZE]
[SIZE=2]end class[/SIZE]
This allows two way binding from my text box lets call it txtAddress4 and it works fine. The problem comes when I make a change to another property of clsCustomer from an event of txtAddress4 such as propertychanged or validating. Let say I update oCustomer.Address3. When I do this it seems to overwrite the change I have made to txtaddress4.text as soon as I tab to the next field - it seems to be overwriting it back from whatever is in the ocustomer.address4 prior to me amending it. This only happens if I try to update another property of the ocustomer object in a txtaddress4 event.

If I set m_NotifyOnPropertyChange = false first then I do not have this problem but this then causes issues with binding.

Has anyone else experienced this issue? Do you have a solution?
 
There is nothing wrong with the notification or binding, they will not cause any change or revert any change by themselves, only user interaction or your code can do that. You should revise the code logic in your PropertyChanged event handler. Whenever you change a notify-enabled property value the PropertyChanged event is raised for that property. Doing such a change from PropertyChanged event handler is not exempt, and naturally this can set off a chain of PropertyChanged events until no more property value changes.
 
There is nothing wrong with the notification or binding, they will not cause any change or revert any change by themselves, only user interaction or your code can do that. You should revise the code logic in your PropertyChanged event handler. Whenever you change a notify-enabled property value the PropertyChanged event is raised for that property. Doing such a change from PropertyChanged event handler is not exempt, and naturally this can set off a chain of PropertyChanged events until no more property value changes.

Hi John, thanks for replying to my question and sorry for the big delay, I got sidelined on another project.

I am not entirely sure I understand what you are saying. Do you mean that the problem I am having shouldn't happen and that there is something wrong with my code because I have just created a quick test program and it does definitely does act as I have described. If I am doing something wrong I need to know what it is.

If you are saying that I shouldn't update properties of oCustomer straight from a textbox.LostFocus event because it will cause this issue then fair enough at least I will know where I stand.

I appreciate your patience.
 
What JohnH is saying is that there is nothing wrong with the code raising the events, but rather with the code handling them. We haven't seen any of that code so we can't say what you might be doing wrong. You mention a quick test program. How about you show us the relevant parts of that?
 
What JohnH is saying is that there is nothing wrong with the code raising the events, but rather with the code handling them. We haven't seen any of that code so we can't say what you might be doing wrong. You mention a quick test program. How about you show us the relevant parts of that?

Here is the test code which recreates the problem:


VB.NET:
'----------------clscustomer class ---------------


Imports System.ComponentModel


Public Class clsCustomer


    Implements INotifyPropertyChanged


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


    Private m_NotifyOnPropertyChange As Boolean = True


    Private mAddress3 As String = ""
    Private mAddress4 As String = ""


    Public Overridable Property Address3() As String
        Get
            Return mAddress3
        End Get


        Set(ByVal Value As String)
            If mAddress3 <> Value Then
                mAddress3 = Value
                NotifyPropertyChanged("Address3")
            End If
        End Set
    End Property


    Public Overridable Property Address4() As String
        Get
            Return mAddress4
        End Get


        Set(ByVal Value As String)
            If mAddress4 <> Value Then
                mAddress4 = Value
                NotifyPropertyChanged("Address4")
            End If
        End Set
    End Property


    Public Property _NotifyOnPropertyChange() As Boolean
        Get
            Return m_NotifyOnPropertyChange
        End Get
        Set(ByVal value As Boolean)
            m_NotifyOnPropertyChange = value
        End Set
    End Property


    Public Sub NotifyPropertyChanged(ByVal PropertyName As String)
        If Me.m_NotifyOnPropertyChange Then
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
        End If
    End Sub




End Class
-------- form1 -----------------------------------------
form1 has two text fields bound to the two customer address properties




VB.NET:
Public Class Form1


    Private mCustomer As clsCustomer




    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        mCustomer = New clsCustomer
        mCustomer.Address3 = "3"
        mCustomer.Address4 = "4"
        Me.ClsCustomerBindingSource.DataSource = mCustomer
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MsgBox("Add3=" & mCustomer.Address3 & vbCr & vbLf & _
                "Add4=" & mCustomer.Address4)
    End Sub




    Private Sub Address3TextBox_LostFocus(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Address3TextBox.LostFocus
        mCustomer.Address4 = "address4"
    End Sub




End Class

If you change the value in address3 then click the button the value reverts to what was there before you changed it.
 
If you change the value in address3 then click the button the value reverts to what was there before you changed it.
I don't see that happening.
 
Actually I can see it if Address4TextBox is first set to a value different than the one you push "address4", when changing Address3TextBox and leaving it the 'revert' occur. The cause is the bindings DataSourceUpdateMode, which defaults to OnValidation. You change the other property on LostFocus (which should be Leave event), and this happens before control is validated. I guess the bindingsource ListChanged event that happens when Address4 property is changed causes the bound controls to re-read current values from the data source, thus reverting Address3TextBox that is not yet committed. Click '(Advanced)' in controls data binding and set DataSourceUpdateMode to OnPropertyChanged.
 
Actually I can see it if Address4TextBox is first set to a value different than the one you push "address4", when changing Address3TextBox and leaving it the 'revert' occur. The cause is the bindings DataSourceUpdateMode, which defaults to OnValidation. You change the other property on LostFocus (which should be Leave event), and this happens before control is validated. I guess the bindingsource ListChanged event that happens when Address4 property is changed causes the bound controls to re-read current values from the data source, thus reverting Address3TextBox that is not yet committed. Click '(Advanced)' in controls data binding and set DataSourceUpdateMode to OnPropertyChanged.

Thanks JohnH, that works fine. It's been bugging me for ages!
 
Back
Top