-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
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
- Selecting a radio button will bind
MyControlto a property inMainPageViewModel. - Pressing
Increasebutton will increase the bound property. MyControl'sLabeldisplays the bound property.
Issue and How To Produce It
- From any checked radio button, switch to the other one.
- Press the
Increasebutton at least once. - Switch to the previous radio button but don't press the
Increasebutton. - 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;
}
}