Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

BindingContext changes are called multiple times on app start #470

Merged
merged 4 commits into from
Nov 16, 2016
Merged

BindingContext changes are called multiple times on app start #470

merged 4 commits into from
Nov 16, 2016

Conversation

adrianknight89
Copy link
Contributor

@adrianknight89 adrianknight89 commented Oct 19, 2016

Description of Change

If you put a view model locator as an App resource and set your binding context in MainPage, the locator gets called multiple times. This happens first when XAML for the main page is being loaded and then when the page is being parented by App.

This PR ensures that binding context changes are not made if the inherited context is the same as the value passed to SetInheritedBindingContext()

Bugs Fixed

PR Checklist

  • Has tests (if omitted, state reason in description)
  • Rebased on top of master at time of PR
  • Changes adhere to coding standard
  • Consolidate commits as makes sense

Copy link
Member

@StephaneDelcroix StephaneDelcroix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually hides a part of the issue*, but I'm ok to go with it, as it fixes the issue at hand, provided you add a unittest for it.

[*] full story here:

  • Bindings are applied on SetInheritedBindingContext even when the context does not change => you fixed this
  • Bindings are applied twice on Parenting; once in set_Parent and a second time in OnChildAdded. => I'm fine if we do not fix this
  • This is not a bug, merely an improvement. We should be able to poke the binding source as often as we find convenient :)

child.Parent = this;
if (Platform != null)
child.Platform = Platform;

child.ApplyBindings();
if(bindingContext == child.BindingContext)
child.ApplyBindings();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, setting Parent should set child binding context, but there are two checks in parent set that return before SetChildInheritedBindingContext() is called. It seemed safer to add this check instead of removing apply bindings altogether. I'll work on unit testing tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's actually safer to leave this part of the code unchanged, and stay with the safe first version of the PR

@StephaneDelcroix StephaneDelcroix self-assigned this Oct 20, 2016
@StephaneDelcroix StephaneDelcroix merged commit 107ed5e into xamarin:master Nov 16, 2016
@rolek
Copy link

rolek commented May 3, 2017

This still happens in v 2.3.4.231

@Szymaniuk
Copy link

Szymaniuk commented Jun 13, 2017

This is merged with what? With master, that's fine, but with which Xamarin.Forms release, because for me it's also not working at 2.3.4.x.

@StephaneDelcroix
Copy link
Member

StephaneDelcroix commented Jun 13, 2017

@Szymaniuk this was released in the 2.3.4 series.

With this PR, and e.g. #983, we're reducing the number of times the Binding gets its source. We still do not consider it a bug. See #470 (review) for explanation.

If you've a case when the Binding is updated when you think it shouldn't, please report a bug to bugzilla, we'll see if this is fixable or not.

@j-fritsch
Copy link

@StephaneDelcroix, thanks for the update. In my case, after updating to 2.3.4, the number of times my ViewModelLocator was called dropped from 3 to 2. However, I think I still need a little more explanation. Sorry if I didn't fully understand your review above.

As described in the bugzilla reports (1) (2), if I set the BindingContext in XAML, my ViewModelLocator will be called multiple times.

<ContentPage
  BindingContext="{Binding Home, Source={StaticResource ViewModelLocator}}">

If I set the BindingContext in the page's constructor in the codebehind, my ViewModelLocator is only called once.

public HomePage()
{
    InitializeComponent();

    var vml = (ViewModelLocator)Application.Current.Resources["ViewModelLocator"];
    BindingContext = vml.Home;
}

Are you saying that is normal, expected behavior? If I want or need it to only be called once, the solution is to just set it in the page's constructor instead?

@StephaneDelcroix
Copy link
Member

@j-fritsch this isn't a wrong behavior, but #983 is supposed to address this anyway.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Viewmodel instantiates twice using a ViewModelLocator
7 participants