I have a ContentPage (actually an MvxContentPage) with ToolbarItems defined. The Items appear in Android and iOS as expected, but do not appear at all in UWP. I have tried setting SetToolbarPlacement to both Top and Bottom manually, in both the constructor and the OnAppearing method. Thus far, I have not been able to affect any change in the UWP application. Am I doing something wrong? Can Mvx not render the Toolbar?
<mvx:MvxContentPage
xmlns:mvx="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
x:TypeArguments="viewModels:CategoryListViewModel"
xmlns:viewModels=""
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GSP.X.AccuStore.Forms.Views.Site.Profiles.CategoryListView">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Areas" Command="{Binding Path=GoToAreasCommand}" />
</ContentPage.ToolbarItems>
</mvx:MvxContentPage>
The problem is you have not add start page to NavigationPage. I have test with the follow code in the blank Xamrin.Froms app, the ToolbarItem display well in the top of MainPage.
public App()
{
InitializeComponent();
var nav = new NavigationPage(new MainPage());
MainPage = nav;
}
Related
I'm developing a cross-platform app (android, IOS) which has to be able to switch languages on each page at the press of a button. I'm using an AppShell for navigation and have the button for the language switch in the toolbar of the AppShell. I made resource files: AppResources.resx and AppResources.fr.resx. I reload both the current page I am on and the AppShell when switching, which seems to have the side effect of going back to the first page I have set on my navigation bar. The reload of the AppShell seems to be necessary as when I don't do it the page seems to go on top and there is no more navigation as well as the color resources I have set in the AppShell get removed. I use the below code to switch the language of my app:
private void Language_switch(object sender, EventArgs e)
{
var lang_switch = Lang.Text;
if (lang_switch == "FR")
{
CultureInfo language = new CultureInfo("fr");
Thread.CurrentThread.CurrentUICulture = language;
AppResources.Culture = language;
Application.Current.Properties[key: "LanguageCode"] = "fr_FR";
}
else
{
CultureInfo language = new CultureInfo("");
Thread.CurrentThread.CurrentUICulture = language;
AppResources.Culture = language;
Application.Current.Properties[key: "LanguageCode"] = "nl_NL";
}
Application.Current.MainPage = new Surveys();
Application.Current.MainPage = new AppShell();
}
This code used to work but is not working anymore. I do remember updating Xamarin Forms a bit ago so this might have something to do with the code not working anymore. In XAML I read from the resource files as below:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyOpinion.Views.Surveys"
xmlns:vm="clr-namespace:MyOpinion.ViewModels"
Title="{Binding Title}"
xmlns:resource="clr-namespace:MyOpinion.Resx">
<Label Text="{x:Static resource:AppResources.Openstaande}" TextColor="{StaticResource Text}" FontSize="24" Margin="0,0,0,10"/>
</ContentPage>
you can use the TranslateExtension provided from Xamarin Community Toolkit. You don't need to reload your pages.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="MyLittleApp.MainPage">
<StackLayout>
<Label Text="{xct:Translate AppResources.ATranslatedMessage}" />
<Label Text="{xct:Translate AppResources.AnotherTranslatedMessage, StringFormat='#{0}'}" />
</StackLayout>
</ContentPage>
You should Initiliaze it first:
LocalizationResourceManager.Current.PropertyChanged += (_, _) => AppResources.Culture = LocalizationResourceManager.Current.CurrentCulture;
LocalizationResourceManager.Current.Init(AppResources.ResourceManager);
After Language change you call:
LocalizationResourceManager.Current.CurrentCulture = newCulture;
Here is documentation
https://learn.microsoft.com/en-us/xamarin/community-toolkit/extensions/translateextension
https://learn.microsoft.com/en-us/xamarin/community-toolkit/helpers/localizationresourcemanager
As #Michael said i dont think either there is a way to change language without poping to Root. Though i dont recommend his idea of copping the navigation stack then pushing the pages. But i will implement the idea for you.
Note that navigation stack in readonly property.
var navStack = Application.Current.MainPage.Navigation.NavigationStack;
Application.Current.MainPage.Navigation.RemovePage(navStack.First());
Application.Current.MainPage = new AppShell ();
foreach (var item in navStack)
{
await Application.Current.MainPage.Navigation.PushAsync((Page)Activator.CreateInstance(item.GetType()));
}
Is there anyway to changed the font size of the ContentPage? enter image description here
Example is that, the last Tab. SUMMARY is cut and I want to set the font size to small.
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Test.ViewModels"
xmlns:model="clr-namespace:Test.Models"
Shell.TabBarBackgroundColor="Transparent"
x:Class="Test.Views.MainPage">
<ContentPage Title="Delivery">
</ContentPage>
<ContentPage Title="Pending">
</ContentPage>
<ContentPage Title="Success">
</ContentPage>
<ContentPage Title="Failed">
</ContentPage>
<ContentPage Title="Summary">
</ContentPage>
</TabbedPage>
I tried adding this:
<NavigationPage.TitleView>
<Label Text="This is my Title" FontSize="12" TextColor="White" />
</NavigationPage.TitleView>
But doesn't do anything.
I was able to reproduce the tab title as the screenshot you privided. You could try the code below to set the TabMode, TabGravity in custom renderer.
[assembly: ExportRenderer(typeof(TabbedPage),
typeof(CustomTabbedPageRenderer))]
namespace App15.Droid
{
class CustomTabbedPageRenderer : TabbedPageRenderer
{
private TabLayout tabLayout = null;
public CustomTabbedPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TabbedPage> e)
{
base.OnElementChanged(e);
this.tabLayout = (TabLayout)this.GetChildAt(1);
tabLayout.TabMode = TabLayout.ModeScrollable;
tabLayout.TabGravity = TabLayout.GravityFill;
}
}
}
Normally, we could set the TextSize in tabbed page custom renderer. But sometimes we would miss the different types if TextView. So i think the way above would be better. You could also check the way to set the TextSize in custom renderer.
Tabbed page custom renderer on Xamarin.Forms
When TabbedPage use android:TabbedPage.ToolbarPlacement="Bottom" to set the tabs in the bottom, the renderer above does not work. You could refer to teh solution in the link below.
How to change Tabbar text size when using TabbedPage.ToolbarPlacement="Bottom" in Xamarin Android?
I am using the Shell template from VS2019 in a Xamarin Forms app.I have two pages listed in the shell flyout.
<FlyoutItem Title="Home" Icon="icon_about.png">
<ShellContent Route="HomePage" ContentTemplate="{DataTemplate local:HomePage}" />
</FlyoutItem>
<FlyoutItem Title="Logoff time" Icon="icon_about.png">
<ShellContent Route="SecondPage" ContentTemplate="{DataTemplate
local:SecondPage}" />
</FlyoutItem>
Using the hamburger menu I navigate away from the Homepage to another page SecondPage. I have a button on the SecondPage which perform an action and from that action I want to navigate back to the HomePage. When I use this code:
var route = $"{nameof(HomePage)}";
await Shell.Current.GoToAsync(route);
The HomePage shows but there is a back button instead of the hamburger menu. If I tap the hamburger icon the page navigates back to the SecondPage.
How do I navgate from SecondPage to HomePage and show the hamburger icon?
With so little information (not knowing the details of how your navigation is implemented) it's hard to help you. But the first things that come to mind are the following you could try.
Try one of the following for popping the SecondPage and navigating back to:
await Shell.Current.Navigation.PopAsync();
or
await Shell.Current.Navigation.PopModalAsync();
And if you have a navigation bar with a back button that you don't want then try this in the HomePage.xaml
NavigationPage.HasNvaigationBar="False"
or
Shell.NavBarIsVisible="False"
The two
//
before the route will accomplish my aims.This resets the root page apparently so HomePage once again become the root page.
var route = $"//{nameof(HomePage)}"
I have solved this issue in my own project; I wanted this page to show up at the start of the application, using the navigation class to push the screen and then pop it when the user clicks a button. I had the same issue of a back button showing up, instead of the hamburger icon, when moving the user to the HomePage. I hope this helps someone in the future.
Classes are as follows:
public partial class AppShell : Xamarin.Forms.Shell {
public AppShell() {
InitializeComponent();
Routing.RegisterRoute(nameof(ItemDetailPage), typeof(ItemDetailPage));
Routing.RegisterRoute(nameof(NewItemPage), typeof(NewItemPage));
Routing.RegisterRoute(nameof(HomePage), typeof(HomePage));
Routing.RegisterRoute(nameof(NewUserPage), typeof(NewUserPage));
this.Navigation.PushAsync(new NewUserPage());
}
}
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class NewUserPage : ContentPage {
public NewUserPage() {
InitializeComponent();
this.BindingContext = new NewUserViewModel();
Shell.SetNavBarIsVisible(this, false);
}
}
class NewUserViewModel : BaseViewModel {
public NewUserViewModel() {
NewUserClickedCommand = new Command(OnNewUserClicked);
}
public Command NewUserClickedCommand { get; }
private async void OnNewUserClicked() {
await Shell.Current.Navigation.PopAsync();
}
}
And the XAML file for NewUserPage:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Project.Views.NewUserPage">
<ContentPage.Content>
<StackLayout>
<Label Text="This is a page for new users"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<Button Text="Click for New User" BackgroundColor="{StaticResource Primary}" Command="{Binding NewUserClickedCommand}"></Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I don't need a MasterDetail until I've navigated through two regular ContentPages first, where I collect information that the MasterDetail will need. The ContentPages make use of the INavigationParameters sent to OnNavigatedTo and OnNavigatedFrom for that collected information.
The the SecondPage viewmodel handles a button command wherein the handler calls the MasterDetail:
NavigationService.NavigateAsync("CompareSelectionsMasterDetail/CompareSelectionsNavigationPage/RangeCircle",
parameters);
Sure enough, the RangeCircleViewModel.OnNavigatedTo receives the parameters. However, when I go back (like with the Android back button), its OnNavigatedFrom is not called, thereby sending null parameters back leaving my ContentPages with no idea what their state was.
The viewmodel for CompareSelectionMasterDetail doesn't do anything and the viewmodel for CompareSelectionsNavigationPage just does this:
public class CompareSelectionsNavigationPage : NavigationPage, INavigationPageOptions
{
public bool ClearNavigationStackOnNavigation => false;
}
I'm not sure what it means to have a NavigationPage in the MasterDetailPage XAML and the separate CompareSelectionsNavigationPage that I call with Prism but if I remove the XAML one, the RangeCircle page doesn't render. If I only have the XAML one and change the Prism navigation to CompareSelectionsMasterDetail/NavigationPage/RangeCircle then I get the same behavior as using both NavigationPages.
My MasterDetail XAML is simple.
> <MasterDetailPage.Master>
> <NavigationPage Title="Required Foo" Icon="hamburger_icon.png">
> <x:Arguments>
> <ContentPage Title="Menu">
> <StackLayout Padding="40">
> <!-- TODO: // Update the Layout and add some real menu items -->
> <Label Text="Hello John"/>
> <Button Text="Range Circle" Command="{Binding NavigateToRangeCircleCommand}" CommandParameter="ViewA" />
> </StackLayout>
> </ContentPage>
> </x:Arguments>
> </NavigationPage> </MasterDetailPage.Master>
Every example I can find of Master Detail (especially with Prism) starts off the app with Master Detail page. I'm not sure if my usage is what breaks OnNavigatedFrom? (Basically ContentPage(Page1)->ContentPage(Page2)->MasterDetail->NavigationPage->NavigationPage->ContentPage(RangeCircle))
The individual ContentPages don't have a problem calling OnNavigatedFrom.
I'm using Prism.Forms 6.3 in a Xamarin.Forms 2.3.4.247 project. I'm having a hard time tracking why the back arrow button isn't visible when I navigate to a details page within a Master/Detail setup.
I can navigate to the Pages just fine, but the back-button never shows up. Instead, the hamburger menu icon is always visible. This is my "Master" page.
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FloatSink.Apps.Mobile.Views.ValueConverters"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="FloatSink.Apps.Mobile.Views.MainPage"
BackgroundColor="Blue">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<StackLayout Padding="40">
<Label Text="Hello" />
<Button Text="Feed" Command="{Binding NavigateCommand}" CommandParameter="NavigationPage/FeedPage" />
<Button Text="Options" Command="{Binding NavigateCommand}" CommandParameter="NavigationPage/OptionsPage" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
</MasterDetailPage>
This is two of my Detail pages.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FloatSink.Apps.Mobile.Views.FeedPage">
<Label Text="Hello from Feed Page!" />
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FloatSink.Apps.Mobile.Views.OptionsPage">
<Label Text="Hello from Options Page!" />
</ContentPage>
I navigate to it using the CommandParameter specified in my Master page, using the navigation service in the MainPageViewModel.
private void NavigateToPage(string uri)
{
this.navigationService.NavigateAsync(uri);
}
I've setup my NavigationPage like this during the startup of the app so I land on the FeedPage first, then I can navigate to the OptionsPage.
public class App : PrismApplication
{
public App(IPlatformInitializer dependencyRegister) : base(dependencyRegister) { }
protected override void OnInitialized()
{
base.NavigationService.NavigateAsync("MainPage/NavigationPage");
}
protected override void RegisterTypes()
{
var builder = new ContainerBuilder();
builder.RegisterModule<NavigationRegistration>();
builder.RegisterModule<ServicesRegistration>();
base.Container.RegisterTypeForNavigation<NavigationPage>();
// This is deprecated but we have to wait for Prism.Autofac to update itself
builder.Update(base.Container);
}
}
The DI registrations associated with navigation are done in this module:
internal class NavigationRegistration : Module
{
/// <summary>
/// Load the navigation related types into the given builder.
/// </summary>
/// <param name="builder">Container Builder that will be turned into the final IOC Container</param>
protected override void Load(ContainerBuilder builder)
{
// Register the NavigationPage in Xamarin with the Prism Navigation system.
//builder.RegisterType<NavigationPage>().AsSelf();
//PageNavigationRegistry.Register(nameof(NavigationPage), typeof(NavigationPage));
// Get all of the Types that represent a View in our assembly for DI and navigation registration
// If start-up time ever becomes an issue, we can replace this assembly scan with explicit registrations.
Type[] viewTypes = base.ThisAssembly.GetTypes().Where(type => type.IsAssignableTo<Page>()).ToArray();
// Iterate over each discovered View Type and register it with the navigation system and DI container.
for(int index = 0; index < viewTypes.Length; index++)
{
Type viewType = viewTypes[index];
builder.RegisterType(viewType).Named<Page>(viewType.Name);
// If we ever need to disconnect a view name from its Type name, we can do so here.
// We would build a custom attribute to decorate the view with, pull the attribute from the Type
// and register the Type with the attribute value.
PageNavigationRegistry.Register(viewType.Name, viewType);
}
}
}
Again I can each one of my detail pages without problem, the hamburger menu exists and I can open the Master page to view my buttons used for navigating. I just can't navigate backwards once I'm there. Is that something I'm supposed to wire up myself?
I'm not sure I'm reading your question right but it sounds like this is normal behavior. In my (short) experience with XF/Prism, every navigation from the master is a beginning of the stack. If you were to add another page, e.g. from Master->PageA->PageB, I would expect Page A to have the hamburger menu but going to PageB would give you the back arrow.
For using NavigationPage inside uri you should register it for navigation in the App.xaml.cs:
protected override void RegisterTypes()
{
// your registrations
Container.RegisterTypeForNavigation<NavigationPage>();
}
I most cases it is the reason.
To Navigate To Master Page
"/MasterPage/NavigationPage/ViewA"
To Navigate out of Master Page from ViewA and with back button
"ViewB"
You need to start your app with MainPage = new NavigationPage(new StartPage()); That is how it is solved in normal situation. So maybe try to register your MainPage wrapped in a NavigationPage.