"PropertyChanged" trigged multiple times.

Jun 21, 2011 at 11:05 AM

I meet that a property of VM was gotten multiple times(the times increase by 1 when I'm getting it next time).
When stept into BindingHelper::InternalNotifyPropertyChanged() -- propertyChanged(sender, new PropertyChangedEventArgs(propertyName)); , the getter of VM's property is trigged more then one times.
So I browsed the source code and notice that "ViewModelBase<TViewModel>::PropertyChanged" is an event. Is the "PropertyChanged +=" binded multiple times?
But I can't find any binding code of event like "PropertyChanged +=".

The following is a part of my project (it's some difficult to devide them).

in VM:

public void Enter(TModel param)
{
    this.AccountInfos = param;
}

public IList<ClientInfoItem> AccountInfos
{
    get
    {
        return this.accountInfos;
    }
    set
    {
        this.accountInfos = value;
        this.NotifyPropertyChanged(m => m.AccountInfos);
    }
}

The call stack:

     Sst.Gui.exe!Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>.AccountInfos.get() Line 58    C#
     [External Code]   
     SimpleMvvmToolkit-WPF.dll!SimpleMvvmToolkit.BindingHelper.InternalNotifyPropertyChanged(string propertyName, object sender, System.ComponentModel.PropertyChangedEventHandler propertyChanged) Line 32 + 0x68 bytes    C#
     SimpleMvvmToolkit-WPF.dll!SimpleMvvmToolkit.BindingHelper.NotifyPropertyChanged<Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>,System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>(System.Linq.Expressions.Expression<System.Func<Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>,System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>> property, object sender, System.ComponentModel.PropertyChangedEventHandler propertyChanged) Line 22    C#
>    SimpleMvvmToolkit-WPF.dll!SimpleMvvmToolkit.ViewModelBase<Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>>.NotifyPropertyChanged<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>(System.Linq.Expressions.Expression<System.Func<Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>,System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>> property) Line 37    C#
     Sst.Gui.exe!Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>.AccountInfos.set(System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem> value) Line 64 + 0x330 bytes    C#
     Sst.Gui.exe!Sst.Gui.ViewModels.ShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>.Enter(System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem> param) Line 80 + 0x19 bytes    C#
     Sst.Gui.exe!Sst.Gui.SceneSwitcher<Sst.Workflow.ViewModelInterfaces.IShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>,System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>.DoSwitchScene(System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem> param) Line 95 + 0x58 bytes    C#
     Sst.Gui.exe!Sst.Gui.SceneSwitcher<Sst.Workflow.ViewModelInterfaces.IShowAccountsViewModel<System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>,System.Collections.Generic.IList<Sst.Workflow.BusinessServiceReference.ClientInfoItem>>.SwitchScene.AnonymousMethod__0() Line 40 + 0x17 bytes    C#
     [External Code]   

Jun 21, 2011 at 12:21 PM
Edited Jun 21, 2011 at 5:25 PM
The code is acting exactly the way it is supposed to. The way the PropertyChanged event works is that the binding in the View's XAML calls the getter whenever the event is fired. That is what enables the value in the UI to update whenever the property setter is called and the event is fired.

Is this causing a problem for you?

Cheers,
Tony
Jun 21, 2011 at 2:02 PM

Dear tony:

Excuse me for my poor English, that I can't fully understand your reply :P. But I noticed the getter of VM's property hits multiple time, while the setter hits one time. Is that normal or something wrong? Or need I provide some code?

Jun 21, 2011 at 5:30 PM

The first time the getter is hit is when the XAML reads the property.  The second time is when you are setting the property in code via your Enter method.  The reason this takes place is that the PropertyChanged event will be fired, prompting the View to invoke the getter and refresh the value displayed by the bound control in the XAML.

This is all expected behavior.  The reason why the setter fires the PropertyChanged event is to enable "two-way" data binding. It means that when you update a property from code the UI will display the new value.

Multiple invocation of the property getter in the VM is usually no problem and takes place whenever the UI needs to display a new value.  If this does not create any problems for you, I would not worry about it.

Cheers,

Tony