Search code examples
bindinglabelmaui

Binding to Entry element does not update entry text more than once - Maui


When binding a value to a Label.Text it works fine but doing the same with Entry.Text I see the initial value but this never updates when the value changes. Here is xaml for Label:

            <Label x:Name="multiplierLabel"  VerticalOptions="Center"
            FontSize="22" 
               HorizontalTextAlignment="Center"
            Text="{Binding Source={x:Reference ControlView}, Path=Multiplier}" 
            Padding="16,0, 0,0"/>

and Entry:

            <Entry 
                HorizontalTextAlignment="Center" 
                TextChanged="Entry_TextChanged"  
                Focused="Entry_Focused"
                Keyboard="Numeric"
                FontSize="22" 
                Text="{Binding Source={x:Reference ControlView}, Path=MultiplierB}"
                >
            </Entry>

Both items are bound to the same value in the View Model:

            Multiplier="{Binding CurrentActionRow.Multiplier}"
            MultiplierB="{Binding CurrentActionRow.Multiplier}"

and the code behind is identical for both:

    public string Multiplier
    {
        get => (string)GetValue(MultiplierProperty);
        set => SetValue(MultiplierProperty, value);
    }

    public static readonly BindableProperty MultiplierProperty =
           BindableProperty.Create(
               nameof(Multiplier),
               typeof(string),
               typeof(ActionRowElement),
               "Multiplier Not Set");

    public string MultiplierB
    {
        get => (string)GetValue(MultiplierBProperty);
        set => SetValue(MultiplierBProperty, value);
    }

    public static readonly BindableProperty MultiplierBProperty =
           BindableProperty.Create(
               nameof(MultiplierB),
               typeof(string),
               typeof(ActionRowElement),
               "MultiplierB Not Set");

Can anybody help get the Text value to update in the Entry element when the bound value changes?


Solution

  • You can try to change the BindingMode of your property to TwoWay.

    I created a demo and did a test, and it works properly on my side.

    You can refer to the following code:

    ChildView.xaml.cs

    public partial class ChildView : ContentView 
    {
        //other code
    
        public string Multiplier
        {
            get => (string)GetValue(MultiplierProperty);
            set => SetValue(MultiplierProperty, value);
        }
    
        public static readonly BindableProperty MultiplierProperty =
               BindableProperty.Create(
                   nameof(Multiplier),
                   typeof(string),
                   typeof(ChildView),
                   defaultBindingMode: BindingMode.TwoWay);
    
        public string MultiplierB
        {
            get => (string)GetValue(MultiplierBProperty);
            set => SetValue(MultiplierBProperty, value);
        }
    
        public static readonly BindableProperty MultiplierBProperty =
               BindableProperty.Create(
                   nameof(MultiplierB),
                   typeof(string),
                   typeof(ChildView),
                   defaultBindingMode: BindingMode.TwoWay);
    
    
        public ChildView()
          {
                InitializeComponent();
          }
    }
    

    ChildView.xaml

    <?xml version="1.0" encoding="utf-8" ?> 
    <ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MauiContentViewApp.ChildView"
                 x:Name="TestControlView"
                 >
        <VerticalStackLayout>
    
            <Label   Text="{Binding Source={x:Reference TestControlView}, Path=Multiplier}"
                VerticalOptions="Center" 
                HorizontalOptions="Center" />
    
            <Entry   Text="{Binding Source={x:Reference TestControlView}, Path=MultiplierB}"
                VerticalOptions="Center" 
                HorizontalOptions="Center" />
    
        </VerticalStackLayout>
    </ContentView>
    

    MainPage.xaml

    <?xml version="1.0" encoding="utf-8" ?> 
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:mauiapp="clr-namespace:MauiContentViewApp"
                 x:Class="MauiContentViewApp.MainPage"
                 x:Name="mainpage"
                 >
    
        <ScrollView>
            <VerticalStackLayout>
    
                <mauiapp:ChildView  
                                   Multiplier="{Binding  TestName}"
                                   MultiplierB="{Binding TestName}"
                                   >
                </mauiapp:ChildView>
    
    
                <Button  Text="Change"  Command="{Binding ChangeNameCommand}"></Button>
    
            </VerticalStackLayout>
        </ScrollView>
    </ContentPage>
    

    MainPage.xaml.cs

     public MainPage() 
          {
                InitializeComponent();
    
                this.BindingContext =  new MyViewModel();
          }
    

    MyViewModel.cs

         public class MyViewModel: INotifyPropertyChanged 
        {
            private string _testName;
            public string TestName
            {
                set { SetProperty(ref _testName, value); }
                get { return _testName; }
            }
    
            public ICommand ChangeNameCommand => new Command(changeMethod);
    
    
            private void changeMethod()
            {
                index++;
    
                TestName = "change data" + index;          
            }
    
            public MyViewModel()
            {
                TestName = "test string";
    
            }
    
            bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
            {
                if (Object.Equals(storage, value))
                    return false;
                storage = value;
                OnPropertyChanged(propertyName);
                return true;
            }
            protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }
    }