I have a simple login page with a single Entry view. The Entry is bound to a property in the ViewModel.
Everything is working fine except the Text becomes null when the device is rotated. I have event listeners set up to adjust styling etc on rotate, but the problem continues whether they are there or not. This behavior only happens on Android, iOS maintains the value correctly.
Note: I have removed identifying information from the samples and replaced with generic terms:
Page Content
<Grid x:Name="apiConnectGrid"> <StackLayout x:Name="apiConnectStack" Orientation="Vertical"> <StackLayout Orientation="Horizontal" HorizontalOptions="Center" Padding="0,0,0,20"> <Image x:Name="welcomeImage" Source="{converter:ImageResource Namespace.Images.companylogo.png}" HeightRequest="50" HorizontalOptions="Center"/> </StackLayout> <Entry x:Name="urlTextEntry" Text="{Binding CompanyUrl}" HorizontalOptions="FillAndExpand" IsTextPredictionEnabled="False" IsSpellCheckEnabled="False" ReturnType="Go" Keyboard="Url" ReturnCommand="{Binding UrlConfirmCommand}" Placeholder="DirectorsLink URL"/> <Button x:Name="continueButton" Text="Continue" Command="{Binding UrlConfirmCommand}" BackgroundColor="#00AEFF" TextColor="White" HorizontalOptions="FillAndExpand" /> </StackLayout> <telerikPrimitives:RadBusyIndicator x:Name="BusyIndicator" AnimationContentHeightRequest="100" AnimationContentWidthRequest="100" AnimationType="Animation6" AnimationContentColor="#253c8d" InputTransparent="True" IsVisible="{Binding IsBusy}" IsBusy="{Binding IsBusy}"> </telerikPrimitives:RadBusyIndicator> </Grid>
Code Behind:
`[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ConnectApiPage : ContentPage, IResponsivePage
{
ConnectApiViewModel _vm
{
get { return BindingContext as ConnectApiViewModel; }
}
public ConnectApiPage()
{
InitializeComponent();
MessagingCenter.Subscribe<ConnectApiViewModel>(this, "InvalidUrlEntered", (sender) => {
DisplayAlert(Constants.INVALID_URL_TITLE, Constants.INVALID_URL_ERROR, "OK");
});
//Register listener for device rotation and initially set up the page layout.
DeviceDisplay.MainDisplayInfoChanged += Page_DisplayChanged;
SetUpPageOrientation(DeviceDisplay.MainDisplayInfo.Orientation);
}
/// <summary>
/// Given a page orientation set up the page layout based on the Device Idiom
/// </summary>
/// <param name="orientation"></param>
public void SetUpPageOrientation(DisplayOrientation orientation)
{
switch (orientation)
{
case DisplayOrientation.Landscape:
switch (Device.Idiom)
{
case TargetIdiom.Phone:
SetUpLandscapeForPhone();
break;
case TargetIdiom.Tablet:
SetUpLandscapeForTablet();
break;
}
break;
case DisplayOrientation.Portrait:
switch (Device.Idiom)
{
case TargetIdiom.Phone:
SetUpPortraitForPhone();
break;
case TargetIdiom.Tablet:
SetUpPortraitForTablet();
break;
}
break;
}
}
/// <summary>
/// The event handler for when the display layout changes.
/// This will usually only be triggered by a device rotation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Page_DisplayChanged(object sender, DisplayInfoChangedEventArgs e)
{
SetUpPageOrientation(e.DisplayInfo.Orientation);
}
/// <summary>
/// Set up the layout of the page for a Tablet in Portrait.
/// </summary>
public void SetUpPortraitForTablet()
{
SetUpGeneralPortrait();
SetUpGeneralTablet();
apiConnectGrid.ColumnDefinitions = (ColumnDefinitionCollection)Application.Current.Resources["TabletPortraitLoginGridColumns"];
apiConnectGrid.RowDefinitions = (RowDefinitionCollection)Application.Current.Resources["TabletPortraitLoginGridRows"];
apiConnectStack.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
BusyIndicator.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
}
/// <summary>
/// Set up the layout of the page for a Phone in Portrait.
/// </summary>
public void SetUpPortraitForPhone()
{
SetUpGeneralPortrait();
SetUpGeneralPhone();
apiConnectGrid.ColumnDefinitions = (ColumnDefinitionCollection)Application.Current.Resources["PhonePortraitLoginGridColumns"];
apiConnectGrid.RowDefinitions = (RowDefinitionCollection)Application.Current.Resources["PhonePortraitLoginGridRows"];
apiConnectStack.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
BusyIndicator.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
}
/// <summary>
/// Set up the layout of the page for all devices in Portrait.
/// </summary>
public void SetUpGeneralPortrait()
{
}
/// <summary>
/// Set up the layout of the page for a Tablet in Landscape.
/// </summary>
public void SetUpLandscapeForTablet()
{
SetUpGeneralLandscape();
SetUpGeneralTablet();
apiConnectGrid.ColumnDefinitions = (ColumnDefinitionCollection)Application.Current.Resources["TabletLandscapeLoginGridColumns"];
apiConnectGrid.RowDefinitions = (RowDefinitionCollection)Application.Current.Resources["TabletLandscapeLoginGridRows"];
apiConnectStack.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
BusyIndicator.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
}
/// <summary>
/// Set up the layout of the page for a Phone in Landscape.
/// </summary>
public void SetUpLandscapeForPhone()
{
SetUpGeneralLandscape();
SetUpGeneralPhone();
apiConnectGrid.ColumnDefinitions = (ColumnDefinitionCollection)Application.Current.Resources["PhoneLandscapeLoginGridColumns"];
apiConnectGrid.RowDefinitions = (RowDefinitionCollection)Application.Current.Resources["PhoneLandscapeLoginGridRows"];
apiConnectStack.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
BusyIndicator.Style = (Style)Application.Current.Resources["LoginColumnRowStyle"];
}
/// <summary>
/// Set up the layout of the page for all devices in Landscape.
/// </summary>
public void SetUpGeneralLandscape()
{
}
/// <summary>
/// Set up the layout of the page for all phones in either orientation.
/// </summary>
public void SetUpGeneralPhone()
{
}
/// <summary>
/// Set up the layout of the page for all tablets in either orientation.
/// </summary>
public void SetUpGeneralTablet()
{
}
}`
The relevant part of ViewModel:
private string _companyUrl; public string CompanyUrl { get { return _companyUrl; } set { _companyUrl= value.Trim(); OnPropertyChanged(); } }