Description
This repo is intentionally made simple to illustrate the issue.
-
A custom control MyControl has a bindable property Value, a Label for displaying Value and a Button for increasing Value.
MyControl is also backed by a view model called MyControlViewModel nested in MyControl.
-
MainPage uses MyControl and has two RadioButton to dynamically bind MyControl to one of two properties (A and B) in MainPageViewModel.

Expected Behavior
- Selecting a radio button will bind
MyControl to a property in MainPageViewModel.
- Pressing
Increase button will increase the bound property.
MyControl's Label displays the bound property.
Issue and How To Produce It
- From any checked radio button, switch to the other one.
- Press the
Increase button at least once.
- Switch to the previous radio button but don't press the
Increase button.
- Switch again to the other one. Here
MyControl's Label no longer displays the bound property.
Example by assuming that at the beginning the checked radio button is A=0 and unchecked one is B=100.
A ---> B followed by pressing Increase button ---> A but not pressing Increase button ----> B
MyControl's Label:
0 ---> 100 and then becomes 101 ---> 0 ----> 0 (thas should be 101).
My Investigation
The property changed event of the bindable property Value is not triggered
in the last switch explained above (A but not pressing Increase button ----> B).
Details for MyControl
<HorizontalStackLayout
Spacing="20"
BindingContext="{x:Reference This}"
x:DataType="{x:Type local:MyControl}">
<Button
Text="Increase"
Command="{Binding ViewModel.IncreaseCommand}" />
<Label
Text="{Binding ViewModel.Value}" />
</HorizontalStackLayout>
public partial class MyControl : ContentView
{
public MyControlViewModel ViewModel { get; } = new();
public MyControl()
{
InitializeComponent();
ViewModel.PropertyChanged += (s, e) =>
{
Debug.WriteLine("\tViewModel Property Changed");
if (e.PropertyName == nameof(MyControlViewModel.Value))
{
if (Value != ViewModel.Value)
{
Value = ViewModel.Value;
}
}
};
}
public static readonly BindableProperty ValueProperty = BindableProperty.Create(
propertyName: nameof(Value),
returnType: typeof(int),
declaringType: typeof(MyControl),
defaultValue: 0,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: (b, o, n) =>
{
Debug.WriteLine("\tValue Property Changed");
if (b is MyControl me && o is int old && n is int @new)
{
if (me.ViewModel.Value != @new)
{
me.ViewModel.Value = @new;
}
}
});
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public partial class MyControlViewModel : ObservableObject
{
[ObservableProperty]
private int _value;
[RelayCommand]
private void Increase() => Value++;
}
}
Details for MainPage
<VerticalStackLayout
Padding="30,0"
Spacing="25">
<RadioButton
x:Name="rba"
Content="{Binding A, StringFormat='A: {0}'}"
CheckedChanged="RadioButton_CheckedChanged" />
<RadioButton
x:Name="rbb"
Content="{Binding B, StringFormat='B: {0}'}"
CheckedChanged="RadioButton_CheckedChanged" />
<local:MyControl
x:Name="mycontrol" />
</VerticalStackLayout>
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel
{
A = 0,
B = 100
};
rba.IsChecked = true;
}
private void RadioButton_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
if (e.Value)
{
Debug.WriteLine("RadioButton Checked");
if (sender == rba)
{
mycontrol.SetBinding(MyControl.ValueProperty, nameof(MainPageViewModel.A));
}
else if (sender == rbb)
{
mycontrol.SetBinding(MyControl.ValueProperty, nameof(MainPageViewModel.B));
}
}
}
public partial class MainPageViewModel : ObservableObject
{
[ObservableProperty]
private int _a;
[ObservableProperty]
private int _b;
}
}
Link to public reproduction project repository
https://github.com/suugbut/MaybeBug
Version with bug
9.0.0 GA
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
Android, Windows
Affected platform versions
No response
Did you find any workaround?
private void RadioButton_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
if (e.Value)
{
Debug.WriteLine("RadioButton Checked");
if (sender == rba)
{
mycontrol.SetBinding(MyControl.ValueProperty, nameof(MainPageViewModel.A));
}
else if (sender == rbb)
{
mycontrol.SetBinding(MyControl.ValueProperty, nameof(MainPageViewModel.B));
}
// by adding either this
mycontrol.Value = mycontrol.ViewModel.Value;
// or this
// mycontrol.ViewModel.Value = mycontrol.Value;
}
}
Relevant log output
Description
This repo is intentionally made simple to illustrate the issue.
A custom control
MyControlhas a bindable propertyValue, aLabelfor displayingValueand aButtonfor increasingValue.MyControlis also backed by a view model calledMyControlViewModelnested inMyControl.MainPageusesMyControland has twoRadioButtonto dynamically bindMyControlto one of two properties (AandB) inMainPageViewModel.Expected Behavior
MyControlto a property inMainPageViewModel.Increasebutton will increase the bound property.MyControl'sLabeldisplays the bound property.Issue and How To Produce It
Increasebutton at least once.Increasebutton.MyControl's Label no longer displays the bound property.Example by assuming that at the beginning the checked radio button is
A=0and unchecked one isB=100.MyControl's Label:My Investigation
The property changed event of the bindable property
Valueis not triggeredin the last switch explained above (
A but not pressing Increase button ----> B).Details for
MyControlDetails for
MainPageLink to public reproduction project repository
https://github.com/suugbut/MaybeBug
Version with bug
9.0.0 GA
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
Android, Windows
Affected platform versions
No response
Did you find any workaround?
Relevant log output