Mark13426
Mark13426

Reputation: 2639

OnPropertyChanged is being called twice for a bindable property

In Xamarin Forms, I created a bindable property like so:

public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(MyItem), typeof(MyGrid), default(MyItem));

public MyItem SelectedItem
{
     get { return (MyItem)GetValue(SelectedItemProperty); }
     set { SetValue(SelectedItemProperty, value); }
}

Here's my constructor:

public MyView()
{
     InitializeComponent();

     PropertyChanged += OnPropertyChanged;
}

protected void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
   if (propertyChangedEventArgs.PropertyName == "SelectedItem")
   {
       // called twice
   }
}

Can somebody explain why property changed event is firing twice? If I create a changed handler in the definition of the bindable property, then the handler is called once.

public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(MyItem), typeof(MyGrid), default(MyItem), null, SelectedItemChanged);

I have noticed the issue exists only in code-behind. If I set the property directly in XAML, property changed event fires once.

Upvotes: 0

Views: 2497

Answers (1)

Chris Shain
Chris Shain

Reputation: 51339

We don't really have enough information to answer this question with certainty, but I can speculate.

Without seeing your SetValue method, my assumption would be that it lacks a short circuit, e.g. "don't do anything if the new value and the old value are the same".

Then my second assumption would be that the control that is being bound to this property is setting it (after being bound). This can happen with list-type controls when SelectedItem is bound.

The resulting chain of events might be something like:

  1. Code sets property
  2. PropertyChanged event is fired
  3. Binding sets the value on a control
  4. Control reports it's value has been changed, and two-way binding sets the value on the ViewModel again
  5. The lack of a short circuit causes the PropertyChanged event to be raised again
  6. The binding sets the value on the control again (to the same value as before)
  7. The control does not report a change, because it's property is short-circuited properly

My guess is that if you were to short circuit your setter (by checking against the existing value and bailing out if they are the same) this behavior would stop.

Upvotes: 3

Related Questions