Bug 41432 - TwoWay binding leads to endless loop on Android
Summary: TwoWay binding leads to endless loop on Android
Status: VERIFIED FIXED
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms ()
Version: 2.2.0
Hardware: PC Mac OS
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2016-06-01 13:55 UTC by Falko Schindler
Modified: 2016-11-07 13:45 UTC (History)
5 users (show)

Tags: Android ac
Is this bug a regression?: ---
Last known good build:


Attachments
Repro project (444.36 KB, application/x-zip-compressed)
2016-06-02 18:14 UTC, E.Z. Hart [MSFT]
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Description Falko Schindler 2016-06-01 13:55:18 UTC
I built a simple (as possible) app to demonstrate this bug. It consists of a Model, a TestPage and the App. A label is two-way bound to the Model.NumberProperty. When modifying the model (or label.Text) value, Android ends in an endless loop (which might eventually even cause a reboot).

    public class Model: BindableObject
    {
        public static readonly BindableProperty NumberProperty = BindableProperty.Create(nameof(Number), typeof(int), typeof(Model), 0);

        public int Number {
            get { return (int)GetValue(NumberProperty); }
            set { SetValue(NumberProperty, (int)value); }
        }
    }

    public class TestPage: ContentPage
    {
        public TestPage()
        {
            var label = new Label{ BindingContext = App.Model };
            label.SetBinding(Label.TextProperty, Model.NumberProperty.PropertyName, BindingMode.TwoWay);

            label.PropertyChanged += (sender, e) => {
                if (e.PropertyName == nameof(label.Text)) {
                    Console.WriteLine("Label.Text changed to " + label.Text);
                    if (int.Parse(label.Text) > 3) {
                        Console.WriteLine("Set to 3");
                        label.Text = "3";
                    }
                }
            };

            Content = new StackLayout {
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
                Children = {
                    label,
                    new Button {
                        Text = "Modify model",
                        Command = new Command(o => App.Model.Number += 1),
                    },
                    new Button {
                        Text = "Modify view",
                        Command = new Command(o => label.Text += "0"),
                    },
                },
            };
        }
    }

    public class App : Application
    {
        public static Model Model = new Model();

        public App()
        {
            MainPage = new NavigationPage(new ContentPage {
                Content = new Button {
                    Text = "Push page",
                    Command = new Command(o => (MainPage as NavigationPage).PushAsync(new TestPage())),
                },
            });
        }
    }

Detailed reproduction:

1. Press "Push page" to open TestPage
2. "Modify model" increments the number as logged on the command line. When exceeding 3, the number is set back to 3.
3. "Modify view" adds a "0" to the label.Text. Again, the number is set back to 3.
4. When going back to MainPage and pushing TestPage again, the trouble starts: While modifying the view still works, modifying the model causes an endless loop.
5. When re-opening the TestPage a third time, "Modify view" also yields an endless loop.

The loop repeats the following output on the command line:

    Label.Text changed to 4 [or 30]
    Set to 3
    Label.Text changed to 3

The strange thing is: label.Text = "3" causes a new PropertyChanged event, which yields the console output but no further modification to the label.Text. But somehow the event is triggered again and again with the old value 4 or 30, respectively. I guess it relates to the underlying Android views, since the problem does not occur on iOS.
Comment 1 E.Z. Hart [MSFT] 2016-06-02 18:13:30 UTC
Confirmed still happening with 2.3.0.46-pre3. Does not occur on iOS or Windows.
Comment 2 E.Z. Hart [MSFT] 2016-06-02 18:14:10 UTC
Created attachment 16178 [details]
Repro project
Comment 3 adrianknight89 2016-10-20 22:48:05 UTC
Was this fixed already? I tested it as of commit #412 and did not see an endless loop. Android seemed to be behaving the same as iOS.

"The strange thing is: label.Text = "3" causes a new PropertyChanged event"

I might be wrong, but I think this is expected behavior.
Comment 4 E.Z. Hart [MSFT] 2016-10-21 02:57:39 UTC
Just tested the repro on 2.3.3.163-pre3 and it is indeed fixed.
Comment 5 E.Z. Hart [MSFT] 2016-10-21 03:00:41 UTC
Thanks for pointing out this is fixed, Adrian!
Comment 6 Parmendra Kumar 2016-11-07 13:45:20 UTC
I have checked this issue and this issue has been fixed in Xamarin.forms 2.3.3-pre4

Hence closing this issue.