I'm new to Xamarin but know some iOS, got someone else's code dumped in my lap to fix some bugs. I've googled quite a bit, but I can't solve this one.
Everything works fine deployed on Android, deployed on iPhone 4/iOS 7.1.2, and simulated as iPhone 6/iOS 9.3 in the iOS simulator.
Problem
The btnNews button is visible in the iOS simulator (iPhone 6/iOS 9.3) but not when the code is deployed to an iPhone 6/iOS 9.3.1.
MainPage.xaml in a portable project
<?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:c="clr-namespace:Cookies;assembly=Cookies"
x:Class="MyCompany.MainPage" Title="MyCompany">
<Grid ColumnSpacing="1" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" x:Name ="buttonsRow"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<c:CookieWebView x:Name="webView" Grid.Row="0" Grid.ColumnSpan="2">
</c:CookieWebView>
<ActivityIndicator x:Name="activityIndicator"
VerticalOptions="FillAndExpand" HorizontalOptions="Center" Grid.Row="0" Grid.ColumnSpan="2" />
<Button x:Name="btnNews" Text="back to news list" BackgroundColor="#E15F59" BorderRadius="0" BorderColor="#E15F59"
TextColor="White" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" BorderWidth="0" IsVisible="False"
HorizontalOptions="FillAndExpand"/>
</Grid>
</ContentPage>
MainPage.xaml.cs MainPage()
namespace MyCompany
{
public partial class MainPage : ContentPage
{
private Button _btnNews;
private ActivityIndicator Loader { get; set; }
private RowDefinition _row;
public const string URL_NEWS = "http://www.mycompany.com/";
public const string QUERY = "master=app";
public static CookieWebView WebView;
public static string CurrentUrl;
bool externalUrlClicked = false;
public MainPage(string url = null)
{
InitializeComponent();
// cookies common : https://github.com/seansparkman/CookiesWebView + nuget package CookiesWebView nuget : https://www.nuget.org/packages/CookieWebView/1.0.0
// ios: http://stackoverflow.com/questions/29768019/cookies-in-web-view-xamarin-ios
NavigationPage.SetHasNavigationBar(this, false);
WebView = this.FindByName<CookieWebView>("webView");
_row = this.FindByName<RowDefinition>("buttonsRow");
Loader = this.FindByName<ActivityIndicator>("activityIndicator");
WebView.Navigated += _webView_Navigated;
WebView.Navigating += WebView_Navigating;
var source = new UrlWebViewSource();
source.Url = GetUrl(!string.IsNullOrEmpty(url) ? url : URL_NEWS);
WebView.Source = source;
ReadCookiesFromSettings();
_btnNews = this.FindByName<Button>("btnNews");
_btnNews.Clicked += _btnNews_Clicked;
// Keep free from iPhone status bar
this.Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
}
}
}
MainPage.xaml.cs _webView_Navigated()
This method runs whenever a link is clicked in the web view. If the url is a "news item page" then btnNews ("Back to news list") should be shown, else btnNews should be hidden. I have set breakpoints to validate that the correct if/else blocks run at appropriate times. The deployed app uses the same urls/web content as the simulated app.
public void _webView_Navigated(object sender, CookieNavigatedEventArgs args)
{
if (externalUrlClicked)
{
args.Url = CurrentUrl;
externalUrlClicked = false;
return;
}
else
CurrentUrl = args.Url;
if (args.Url != GetUrl(URL_NEWS))
{
_row.Height = 50;
_btnNews.IsVisible = true;
}
else
{
_row.Height = 0;
_btnNews.IsVisible = false;
}
try
{
var cookie = WebView.Cookies[Settings.CookiesSettingsKey];
Settings.CookiesSettings = cookie.Value;
}
catch (Exception)
{
}
Loader.IsVisible = Loader.IsRunning = false;
}
In a native iOS app I would have started investigating layout and things like setNeedsDisplay, but I haven't yet found out how to do that with Xamarin.
Thanks for helping out!
Related
I am trying to auto-wire up the ViewModel using prismMvvm:ViewModelLocator.AutoWireViewModel="True" in my View. For UWp it working perfectly. But with-in Android and WASM, View not able to wire up the ViewModel in my Uno platform Application using Prism.
<UserControl
x:Class="RepayablClient.Shared.Views.Login"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prismMvvm="using:Prism.Mvvm"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
prismMvvm:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d">
<Grid Background="#881798">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
Width="250"
Height="300"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Source="/Assets/Icon.png"
Stretch="Fill" />
<TextBlock Grid.Row="1" Text="{Binding LoginUser}" />
<ProgressBar
Grid.Row="2"
Width="250"
Margin="0,20,0,0"
Foreground="White"
IsIndeterminate="True"
ShowError="False"
ShowPaused="False" />
</Grid>
</Grid>
</UserControl>
using Microsoft.Identity.Client;
using RepayablClient.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RepayablClient.Shared.ViewModels
{
public class LoginViewModel : ViewModelBase
{
//public ICommand LoginCommand { get; set; }
string graphAPIEndpoint = "https://graph.microsoft.com/v1.0/me";
private string _loginUser;
public string LoginUser
{
get { return _loginUser; }
set
{
_loginUser = value;
RaisePropertyChanged();
}
}
public LoginViewModel()
{
Title = "Login Page";
LoginUser = "Attempt to Login";
_ = LoginCommandExecutedAsync();
//LoginCommand = new AsyncCommand(LoginCommandExecutedAsync);
}
private async Task LoginCommandExecutedAsync()
{
AuthenticationResult authResult = null;
IEnumerable<IAccount> accounts = await App.publicClientApplication.GetAccountsAsync().ConfigureAwait(false);
IAccount firstAccount = accounts.FirstOrDefault();
try
{
authResult = await App.publicClientApplication.AcquireTokenSilent(Consts.Scopes, firstAccount)
.ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");
try
{
authResult = await App.publicClientApplication.AcquireTokenInteractive(Consts.Scopes)
.ExecuteAsync();
}
catch (MsalException msalex)
{
// await DisplayMessageAsync($"Error Acquiring Token:{System.Environment.NewLine}{msalex}");
}
}
catch
{
// await DisplayMessageAsync($"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}");
return;
}
if (authResult != null)
{
var content = await GetHttpContentWithTokenAsync(graphAPIEndpoint,
authResult.AccessToken).ConfigureAwait(false);
LoginUser = content;
}
}
public async Task<string> GetHttpContentWithTokenAsync(string url, string token)
{
var httpClient = new System.Net.Http.HttpClient();
System.Net.Http.HttpResponseMessage response;
try
{
var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
// Add the token in Authorization header
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
response = await httpClient.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
return content;
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
}
For more details visit my repo: https://github.com/avikeid2007/Repayabl
You're facing an issue that is still standing in Uno, that will be adjusted soon. Basically, if you use a UserControl, some of the properties defined there may not be taken into account when the control is created.
You can fix this in one of two ways:
Change the UserControl to a ContentControl
Add the following property in your csproj:
<UnoSkipUserControlsInVisualTree>false</UnoSkipUserControlsInVisualTree>
This issue is a remnant of a time where Android had a very short UI Thread stack space, and that every layer in the visual tree counted. It's not as critical anymore.
Ok, so I am trying to add a searchbar in the toolbar of my page.
The Search bar appears correctly in the toolbar and I can catch the on text changed event.
I created a new Xaml and cs page and changed content page to 'MySearchContentPage'
I Tried to add a grid and label on my new page created but nothing will show except for the searchbar. I added this just to see if I can get anything to display.
Am I adding it in the right place ? Or how do you add content to this page ?
I have done this by doing the following:
MySearchContentPage Class:
public class MySearchContentPage : ContentPage, ISearchPage
{
public MySearchContentPage()
{
SearchBarTextChanged += HandleSearchBarTextChanged;
}
public event EventHandler<string> SearchBarTextChanged;
public void OnSearchBarTextChanged(string text) => SearchBarTextChanged?.Invoke(this, text);
void HandleSearchBarTextChanged(object sender, string searchBarText)
{
//Logic to handle updated search bar text
}
}
ISearchPage:
public interface ISearchPage
{
void OnSearchBarTextChanged(string text);
event EventHandler<string> SearchBarTextChanged;
}
iOS renderer page:
public class MySearchContentPageRenderer : PageRenderer, IUISearchResultsUpdating
{
readonly UISearchController searchController;
bool _isFirstAppearing = true;
public override void WillMoveToParentViewController(UIViewController parent)
{
base.WillMoveToParentViewController(parent);
var searchController = new UISearchController(searchResultsController: null)
{
SearchResultsUpdater = this,
DimsBackgroundDuringPresentation = false,
HidesNavigationBarDuringPresentation = true,
HidesBottomBarWhenPushed = true
};
searchController.SearchBar.Placeholder = "Search Symptoms";
parent.NavigationItem.SearchController = searchController;
DefinesPresentationContext = true;
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
//Work-around to ensure the SearchController appears when the page first appears https://stackoverflow.com/a/46313164/5953643
if (_isFirstAppearing)
{
ParentViewController.NavigationItem.SearchController.Active = true;
ParentViewController.NavigationItem.SearchController.Active = false;
_isFirstAppearing = false;
}
}
public void UpdateSearchResultsForSearchController(UISearchController searchController)
{
if (Element is ISearchPage searchPage)
searchPage.OnSearchBarTextChanged(searchController.SearchBar.Text);
}
public MySearchContentPageRenderer()
{
var searchControllerr = new UISearchController(searchResultsController: null)
{
SearchResultsUpdater = this,
DimsBackgroundDuringPresentation = false,
HidesNavigationBarDuringPresentation = false,
HidesBottomBarWhenPushed = true
};
searchControllerr.SearchBar.Placeholder = string.Empty;
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
UINavigationBar.Appearance.TitleTextAttributes = new UIStringAttributes
{
ForegroundColor = UIColor.Red
};
}
public override void ViewDidLoad()
{
// base.ViewDidLoad();
// NavigationController.NavigationBar.PrefersLargeTitles = true;
// NavigationController.NavigationBar.BackgroundColor = UIColor.Red;
// var searchController = new UISearchController(searchResultsController: null);
// searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Default;
// searchController.SearchBar.BackgroundColor = UIColor.Green;
// NavigationItem.SearchController = searchController;
// NavigationItem.HidesSearchBarWhenScrolling = false;
//searchController.SearchBar.SizeToFit();
//searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Prominent;
////NavigationController.TabBarController
//this.sea
//NavigationController.TabBarController.NavigationItem.HidesSearchBarWhenScrolling = true;
//NavigationController.TabBarController.NavigationItem.SearchController = searchController;
//this.Title = "Search";
}
}
So far the outcome is this :
I can't seem to get anything else to add to this page. Can anyone explain why?
AddSymptomNew.xaml page:
<?xml version="1.0" encoding="UTF-8"?>
<visiblegyapp:MySearchContentPage
xmlns:visiblegyapp="clr-namespace:VisiblegyApp"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VisiblegyApp.AddSymptomNew"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.LargeTitleDisplay="Always"
Title="Search Symptoms"
BackgroundColor="{DynamicResource BasePageColor}"
>
<ScrollView
x:Name="outerScrollView"
Padding="0"
>
<Grid
x:Name="layeringGrid"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="test label" TextColor="Red" Grid.Row="1"/>
</Grid>
</ScrollView>
The cause is ContentPage is inheritable while XAML is not inheritable.
I would recommend you to use a custom contentview and add this contentView to MySearchContentPage .
For example, create a custom contentView here:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
And in Xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView 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"
x:Class="App132.AddSymptomNewView">
<ContentView.Content>
<ScrollView
x:Name="outerScrollView"
Padding="0">
<Grid
x:Name="layeringGrid"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="test label" TextColor="Red" Grid.Row="1"/>
</Grid>
</ScrollView>
</ContentView.Content>
</ContentView>
And use it in the MySearchContentPage :
<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"
xmlns:app132="clr-namespace:App132"
mc:Ignorable="d"
x:Class="App132.MainPage">
<app132:AddSymptomNewView/>
</ContentPage>
I have added TitleView in MainPage to show on Navigationbar but it shows only for MainPage when I navigate to some other page Navigationbar displaying empty.
Below code I have in MainPage.xaml file
<NavigationPage.TitleView>
<RelativeLayout HorizontalOptions="Fill"
<Image Source="bell.png" HeightRequest="25" WidthRequest="25" x:Name="imgBell"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Height,
Factor=0.018,Constant=10}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding GetStaffAnnouncementCommand}"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
<Label FontSize="10" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" BackgroundColor="Transparent" Text="2" TextColor="Red"
HeightRequest="22" WidthRequest="23" x:Name="labelText">
</Frame>
</RelativeLayout>
</NavigationPage.TitleView>
When I click on bell icon and move to second page TitleView not displaying at all
How can I display TitleView common for all pages?
I wrote a demo about your needs.
There is GIF.
You could Write a custom page inherits from 'ContentPage' and add toolbar item to it.
Update
I achieve it with DependencyService, If you want to know more details about how to achieve DependencyService, you could refer to this blog and my code.
https://www.xamboy.com/2018/03/08/adding-badge-to-toolbaritem-in-xamarin-forms/
There is code that used DependencyService.
Custom ToolbarPage
public class ToolbarPage : ContentPage
{
public ToolbarItem toolbarItem;
public static int item;
public ToolbarPage()
{
// public ToolbarItem(string name, string icon, Action activated, ToolbarItemOrder order = ToolbarItemOrder.Default, int priority = 0);
toolbarItem =new ToolbarItem();
toolbarItem.Icon = "ring2.png";
toolbarItem.Order = ToolbarItemOrder.Primary;
// toolbarItem.Text = item+"";
toolbarItem.Priority = 0;
toolbarItem.Clicked += ToolbarItem_Clicked;
ToolbarItems.Add(toolbarItem);
if (item >= 1)
{
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, toolbarItem, $"{item}", Color.Red, Color.White);
}
}
private void ToolbarItem_Clicked(object sender, EventArgs e)
{
item = item + 1;
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, toolbarItem, $"{item}", Color.Red, Color.White);
}
}
Main.cs
public partial class MainPage : ToolbarPage
{
public MainPage()
{
InitializeComponent();
bt1.Text = ToolbarPage.item.ToString();
bt1.Clicked += async (o, e) =>
{
await Navigation.PushAsync(new HelloToolbarInher());
};
}
protected override async void OnAppearing()
{
//You must make a delay,
await Task.Delay(100);
bt1.Text = ToolbarPage.item.ToString();
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, toolbarItem, $"{ToolbarPage.item}", Color.Red, Color.White);
}
}
Do not forget to change MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<local:ToolbarPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:NaviagationViewDemo"
x:Class="NaviagationViewDemo.MainPage">
<StackLayout>
<!-- Place new controls here -->
<Button
x:Name="bt1"
Text="click"
></Button>
</StackLayout>
There is my new demo.
https://github.com/851265601/NewNaviagationViewDemo
I need help understanding how I can bind a ContentView's Content's to my Xamarin page. I have tried maybe 20 different methods and I can only get the binded contentview to render when I don't use bindings and set the property directly.
<ContentPage.Content>
<Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" x:Name="GridLayout" RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<nav:NavView Grid.Row="0" Grid.Column="0" Padding="0,0,0,0" Margin="0,0,0,0" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand"
HeightRequest="60" x:Name="nav"/>
<ContentView BindingContext="{Binding MainView}" Grid.Row="1" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</Grid>
</ContentPage.Content>
and then below is my code behind
public partial class DetailLayoutView : ContentPage, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
private ContentView mainView;
public ContentView MainView
{
get { return mainView; }
set
{
mainView = value;
OnPropertyChanged("MainView");
}
}
public DetailLayoutView()
{
InitializeComponent ();
MainView = new PyxusChatView();
BindingContext = MainView;
}
}
Can someone help guide me to the right direction? I dont have the bandwidth to implement an entire MVVM refactor at this time I would just like to know how I can achieve this w/ minimal code.
DETECT WHEN A UI IS RENDERED IOS & ANDROID BELOW...
public DetailLayoutView()
{
InitializeComponent ();
MainContentArea.LayoutChanged += MainContentArea_LayoutChanged;
}
private void MainContentArea_LayoutChanged(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(() => {
//UI Is now visible, send a msg to let everyone subscribed to "UpdateDetailView" event now that the
//detail page was changed and it is now okay to make API calls!
MessagingCenter.Send<ContentView, string>(MainView, "UpdateDetailView", "From BlePairingViewModel");
});
}
YOU HAVE SENT MSG NOW YOU CAN MAKE API CALLS & YOUR UI IS VISIBLE W/O MVVM... ALTHOUGH MVVM WOULD BE A BETTER PRACTICE TO INDIVIDUALS W/ MORE TIME TO CODE..
MessagingCenter.Subscribe<ContentView, string>("Pyx", "UpdateDetailView", (sender, arg) =>
{
if (sender == this)
{
Task.Run(async () =>
{
await OnAppearing();
});
}
});
I AM NOT ADVISING THIS AS BEST PRACTICE BUT IT DOES ANSWER THE QUESTION
I have created a simple app, where users can see more information in section, if they tab a Label, which is seen on the pictures below.
The problem is, that after navigating to AnotherPage and back, the text moves to left, even though I have set the HorizontalTextAlignment to End.
This only happens, when I have shown the section and hiding it again (by tapping on the Label twice).
The problem is illustrated on the picture below, where y is located at the left side.
My source code for showing a simple app with this problem, can be downloaded from this Dropbox link.
EDIT
Added code example
The ContentPage is as simple as
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="Test" VerticalOptions="Start" />
<Label Text="{Binding Text}" HorizontalTextAlignment="End" TextColor="Red" HorizontalOptions="FillAndExpand" BackgroundColor="Yellow">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ChangeVisibilityCommand}" />
</Label.GestureRecognizers>
</Label>
</Grid>
<StackLayout IsVisible="{Binding IsVisible}">
<Label Text="Text 1" />
<Label Text="Text 2" />
</StackLayout>
<Button Command="{Binding OpenAnotherPageCommand}" Text="Open Another Page" />
</StackLayout>
And the ViewModel is shown below
public class MainPageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ICommand _changeVisibilityCommand;
public ICommand ChangeVisibilityCommand
{
get => _changeVisibilityCommand;
set
{
if (value != _changeVisibilityCommand)
{
_changeVisibilityCommand = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ChangeVisibilityCommand)));
}
}
}
private bool _isVisible;
public bool IsVisible
{
get => _isVisible;
set
{
if (value != _isVisible)
{
_isVisible = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsVisible)));
}
}
}
private ICommand _openAnotherPageCommand;
public ICommand OpenAnotherPageCommand
{
get => _openAnotherPageCommand;
set
{
if (value != _openAnotherPageCommand)
{
_openAnotherPageCommand = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OpenAnotherPageCommand)));
}
}
}
private string _text = "u";
public string Text
{
get => _text;
set
{
if (!string.Equals(_text, value, StringComparison.InvariantCultureIgnoreCase))
{
_text = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
}
}
}
public MainPageViewModel()
{
ChangeVisibilityCommand = new Command(() =>
{
IsVisible = !IsVisible;
Text = IsVisible ? "x" : "y";
});
OpenAnotherPageCommand = new Command(() =>
{
(Application.Current.MainPage as NavigationPage)?.PushAsync(new AnotherPage());
});
}
}
And the AnotherPage is simply showing a text for example
First of all, i wasn't able to reproduce your issue using the latest version of Xamarin. Maybe simply upgrading Xamarin (Forms) will remove the unwanted behavior in your case as well.
If not, you have two options:
1 - Use HorizontalOptions instead
HorizontalOptions="EndAndExpand"
since HorizontalOptions has a higher priority in the layout engine.
Not the most elegant way but surely the most reliable.
2 - Use DataBinding
In your model just add the following property:
public TextAlignment LabelAlignment
{
get => labelAlignment;
set
{
labelAlignment = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LabelAlignment)));
}
}
private TextAlignment labelAlignment = TextAlignment.End;
And in your Xaml you change HorizontalAlignment to
HorizontalTextAlignment="{Binding LabelAlignment}"
That will work because after your screen has been created, the values in the model will be loaded and updated afterwards.
Change HorizontalOptions="FillAndExpand"
To HorizontalOptions="CenterAndExpand"
This will force the text to expand from the center and be placed at the end.
To force the text to the right, you can add a another column definition to your grid:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
Place and emtpy object into the first cell, the one to the left:
number from the top (0)
number from the left (0)
and your label into the second cell, the one to the right:
number from the top (0)
number from the left (1)
The text area will adjust to the text length and will always be to the right.
I hope this information helps!
You can read more about grid in the documentation:
https://learn.microsoft.com/en-us/xamarin/android/user-interface/layouts/grid-layout