0
votes

In have a project where I have three Entry controls on the screen. They are all bound to backing properties that all have text in them. When I run the app, only the entry control that has focus will show its text. The other entry controls will not show their text until they receive focus. I have report the problem to Microsoft. I was just curious if anyone else had encountered the problem and found a work around until it is fixed. ( I am running as a UWP project)

Steps to Replicate. Create a new Xamarin forms app called EntryControlError. Please include a UWP project in the solution.

Once the project is created, open the MainPage.xaml file and replace all the contents with the XAML below:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             BackgroundColor="#D0E1F9"
             x:Class="EntryControlError.MainPage">

    <ContentPage.Content>
        <StackLayout x:Name="slFullPage" Orientation="Vertical" HorizontalOptions="Fill" VerticalOptions="FillAndExpand" Margin="0,32,0,0" Padding="0,0,0,0">
            <ScrollView HorizontalOptions="Fill" VerticalOptions="FillAndExpand">
                <StackLayout Orientation="Vertical" HorizontalOptions="Fill" VerticalOptions="FillAndExpand">
                    <StackLayout x:Name="slTextHeader" Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Start">
                        <Label x:Name="lblTextHeaderInfo" Text="Enter Text - Max Three Lines" HorizontalOptions="Center" VerticalOptions="Start"
                               TextColor="#283655" FontAttributes="Bold" FontSize="Small" />

                        <Entry x:Name="txtHeaderText1" HorizontalOptions="Fill" VerticalOptions="Start" Text="{Binding KioskHeaderText1, Mode=TwoWay}" 
                               TextColor="#283655" HorizontalTextAlignment="Center" FontAttributes="Bold" FontSize="Medium"  />
                        <Entry x:Name="txtHeaderText2" HorizontalOptions="Fill" VerticalOptions="Start" Text="{Binding KioskHeaderText2, Mode=TwoWay}" 
                               TextColor="#283655" HorizontalTextAlignment="Center" Margin="0,-8,0,0" FontAttributes="Bold" FontSize="Medium" />
                        <Entry x:Name="txtHeaderText3" HorizontalOptions="Fill" VerticalOptions="Start" Text="{Binding KioskHeaderText3, Mode=TwoWay}" 
                               TextColor="#283655" HorizontalTextAlignment="Center" Margin="0,-8,0,0" FontAttributes="Bold" FontSize="Medium" />
                    </StackLayout>
                </StackLayout>
            </ScrollView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Replace everything in the MainPage.xaml.cs file with the following:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Xamarin.Forms;

namespace EntryControlError
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _KioskHeaderText1;
        public string KioskHeaderText1
        {
            get { return _KioskHeaderText1; }
            set
            {
                _KioskHeaderText1 = value;
                OnPropertyChanged();
            }
        }
        private string _KioskHeaderText2;
        public string KioskHeaderText2
        {
            get { return _KioskHeaderText2; }
            set
            {
                _KioskHeaderText2 = value;
                OnPropertyChanged();
            }
        }
        private string _KioskHeaderText3;
        public string KioskHeaderText3
        {
            get { return _KioskHeaderText3; }
            set
            {
                _KioskHeaderText3 = value;
                OnPropertyChanged();
            }
        }

        public MainPage()
        {
            try
            {

                InitializeComponent();
                NavigationPage.SetHasNavigationBar(this, false);
                NavigationPage.SetHasBackButton(this, false);

                KioskHeaderText1 = "Line 1 Text";
                KioskHeaderText2 = "Line 2 Text";
                KioskHeaderText3 = "Line 3 Text";

                txtHeaderText1.BindingContext = this;
                txtHeaderText2.BindingContext = this;
                txtHeaderText3.BindingContext = this;
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error: " + ex.Message);
            }
        }

        /// <summary>
        /// Manual Notification to subscribers that a property has changed. 
        /// </summary>

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }

}

Run the app and the screen will look like:

enter image description here

If you click into the second or third entry control without entering anything, their bound text will automatically appear.

2
first, you don't need to set the BindingContext for each Entry. Just set it once for the page. second, testing for the length of the Entrys in the constructor probably won't work, because the control binding hasn't happened yet. Third, manually setting the value of the Text properties defeats the purpose of using data binding in the first place. Finally, you are not implementing INotifyPropertyChanged. None of these may be related to the problem you're seeing, but they are all fairly unusual approaches. - Jason
OK this is just an example to replicate the problem. I am not going to do an entire MVVM setup for the example. And not in my project I cannot just bind the page as there are other things on the page bound to other view modes. Also I don't test in the constructor, I test in onappearing - which does not matter because that does not work. Finally, I do implement INotifyPropertyChanged in my project. I just did not do that in my sample as I was not going to include that part. - George M Ceaser Jr
then you should file an issue with Xamarin and include a minimal reproducible example - Jason
If you see in my question - I stated I already opened a problem ticket with Microsoft. My question was asking if anyone else has encountered this issue and found a work around I could implement while we wait for Microsoft to fix it. My comment to Cherry's reply I put a link to the MS ticket - George M Ceaser Jr

2 Answers

0
votes

According to Jason's opinion, you don't need to set each entry BindingContext, just set the current Page BindingContext.

Then you create three properties, don't implement INotifyPropertyChanged interface, so when these properties changed, you can not update UI.

I modify your code about binding part, you can take a look:

 public partial class Page6 : ContentPage, INotifyPropertyChanged
{

    private string _KioskHeaderText1;
    public string KioskHeaderText1
    {
        get { return _KioskHeaderText1; }
        set
        {
            _KioskHeaderText1 = value;
            RaisePropertyChanged("KioskHeaderText1");
        }
    }
    private string _KioskHeaderText2;
    public string KioskHeaderText2
    {
        get { return _KioskHeaderText2; }
        set
        {
            _KioskHeaderText2 = value;
            RaisePropertyChanged("KioskHeaderText2");
        }
    }
    private string _KioskHeaderText3;
    public string KioskHeaderText3
    {
        get { return _KioskHeaderText3; }
        set
        {
            _KioskHeaderText3 = value;
            RaisePropertyChanged("KioskHeaderText3");
        }
    }
    public Page6()
    {
        InitializeComponent();

        KioskHeaderText1 = "Line 1 Text";
        KioskHeaderText2 = "Line 2 Text";
        KioskHeaderText3 = "Line 3 Text";


        this.BindingContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;     
    public void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }


}

Finally, because you have used binding for Entry, so I don't suggest you change Entry text directly, you can change KioskHeaderText1 ,KioskHeaderText2 ,KioskHeaderText3 properties to change Entry text.

0
votes

It appears the later releases of Xamarin Forms have fixed the issues. If you are still encountering the challenge, ensure your Xamarin Forms is up to date.