Prism Xamarin Forms Tabbed Page Navigation - c#

I have a Xarmarin Forms application using Prism and Unity and am having trouble with navigation to a tabbed page.
I'm using the following versions: Prism.Forms v6.1.0-pre5 Prism.Unity.Forms v6.2.0-pre5 Xamarin.Forms v2.3.0.38-pre2
My tabbed page looks like this
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:local="clr-namespace:ServiceOrdersMobileApps.Views;assembly=ServiceOrdersMobileApps"
x:Class="ServiceOrdersMobileApps.Views.ServiceOrderTabs">
<NavigationPage Title="Summary">
<x:Arguments>
<local:ServiceOrderSummary />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Complete">
<x:Arguments>
<local:ServiceOrderDetails />
</x:Arguments>
</NavigationPage>
</TabbedPage>
I'm trying to navigate to the tabbed page with the Service Order Detail Page selected but when I navigate according to this blog post. It navigates past the tabbed page to a separate Service Order Detail Page
var p = new NavigationParameters();
p.Add("serviceorder", context);
await _navigationService.NavigateAsync($"{nameof(ServiceOrderTabs)}/{nameof(ServiceOrderDetails)}",p);

You have the page wrapped in a generic NavigationPage that Prism doesn't know about. You need to create a derived NavigationPage and register it for navigation. Then use that to wrap your COntentPages. Then you can try navigating like "ServiceOrdersTabs/MyNavigationPage/ServiceOrdersDetails".
But even this may not work now that I think about it, because you'll have multiple instances of the same NavigationPage and Prism will use the first one it finds and use that.
For a work around, you'll have to create a different NavigationPage for each tab (ServiceOrderSummaryNavPage, ServiceOrdersDetailsNavPage, etc) to ensure that each Tab is unique.
By the way, from where are you navigating?

Related

Display a ToolBar in a Xamarin.Forms modal page

The "new" and recommended way to display a modal page with the Xamarin.Forms Shell uri-based navigation is to set this tag in the XAML file (source): Shell.PresentationMode="ModalAnimated"
and to navigate to it by using a standard route and invoking it with the function Shell.Current.GoToAsync("routeToMyPage").
However, this displays the modal page without a toolbar. Without Shell navigation, I would have wrapped this page in a NavigationPage, but since the pages are initialized through reflection (at least that's what it looks like - don't quote me on this), I don't know how to do that.
Adding a ToolbarItem in the page's XAML code doesn't solve this, neither does the Shell.NavBarIsVisible="True" property, and adding a Button in the Shell.TitleView tag doesn't display a toolbar either.
Is there a way to display the default navigation toolbar without rendering a custom one myself?
Here is the XAML code I used to try to have the Toolbar displayed:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Shell.PresentationMode="ModalAnimated"
Shell.NavBarIsVisible="True"
x:Class="StackOverflow.Views.MyModalPage">
<ContentPage.ToolbarItems >
<ToolbarItem Text="Hi"/>
</ContentPage.ToolbarItems>
<Shell.TitleView>
<Button Text="Toolbar Button"/>
</Shell.TitleView>
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
Edit: I have created a small sample project to showcase my issue: https://github.com/Kuurse/StackOverflowExample
You can first create the NavigationPage root page in the app class:
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
}
Then set like this in your mainpage.xaml:
<?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="StackOverflow.Views.MyModalPage"
NavigationPage.HasNavigationBar="True">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Hi"/>
</ContentPage.ToolbarItems>
</ContentPage>
By the way, do you want to display only the default navigation toolbar?

ListView navigation using Xamarin.Forms Shell

I am trying to figure out how to make my application a Shell application.
This is my shell.xaml.
<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:Project.View"
x:Class="Project.AppShell">
<ShellContent Title=""
ContentTemplate="{DataTemplate views:MainPage}"/>
<ShellContent Title=""
ContentTemplate="{DataTemplate views:ListView}"
Route="StockListView"/>
</Shell>
I am having trouble to make sense of the routing, my goal is to make routing from the listview to another view, like below.
MainView
ListView
ViewItem
I don't find it clear how to implement this, since the listview is not one of the three main hierachical objects, at least not obvious for me.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/introduction
. I can get it to work by changing the page from my viewmodel that is connected to my listview.
App.Current.Mainpage = View
But it feels like I am mixing things up and that it should be possible to use Shell routing in some way, is this possible?
First you need to register the route, you can register the route in the xaml page or register the route in the back-end code.
For more information you can refer to: Register routes.
After registering the route you can use await Shell.Current.GoToAsync("//ListView/ViewItem"); code to make the call elegantly.
Please take care of the use of routes multiple levels(route hierarchy).
For the detailed usage of route navigation, you can check: Perform navigation.

PopToRootAsync to a selected Shell Flyout Item

I have this code below to create an action bar with an integrated side bar using <Shell> so the user can navigate easily by swiping right. Being new to C#, I understand that the first ShellContent is gonna be the page to be loaded and previewed by the <Shell> when the app opens which is ContentTemplate="{DataTemplate local:LoanHistory}"
I also understand when you click on the FlyoutItems you aren't gonna add stack to the navigation but the <Shell> is changing the contents each time you click on it. This code below is in a file called MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<Shell 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:local="clr-namespace:LoanApp2.Views"
mc:Ignorable="d"
x:Class="LoanApp2.MainPage" BackgroundColor="#62bef0" Title="Dylan">
<FlyoutItem Title="MyTabApp" Shell.TabBarIsVisible="False" FlyoutDisplayOptions="AsMultipleItems">
<ShellContent Title="Loan History" IsTabStop="False" ContentTemplate="{DataTemplate local:LoanHistory}"/>
<ShellContent Title="Apply for Loan" IsTabStop="False" ContentTemplate="{DataTemplate local:LoanApplication}"/>
<ShellContent Title="Logout" IsTabStop="False" ContentTemplate="{DataTemplate local:LoanHistory}"/>
</FlyoutItem>
</Shell>
So, via the side bar (shell) - I click on Apply for Loan which takes me to LoanApplication.xaml. By this time, no stack is added to the navigation. In the LoanApplication.xaml, I'm using PushAsync binded to a button to take me to a page called AmountLoanable.xaml. This gets added to the stack and the back button on the action bar is now available.
After I am done with the stuff on AmountLoanable.xaml, I use PopToRootAsync to remove the navigation stack except for the root page (which is the <Shell>, MainPage.xaml). However, it takes me back to the "Apply for Loan" which was selected prior, what I want to happen is for it to load a fresh new <Shell>, MainPage.xaml page. In that way, the first page (Loan History) will be the one selected instead of the last page accessed via <Shell>
try to reset your Application.Current.MainPage to your default Shell ex: Application.Current.MainPage = new AppShell();

Hiding a tab in Xamarin.Forms using Prism framework

I am working on a Xamarin Forms project that uses an MVVM pattern and Prism.
My issue is, I need to be able to hide a tab on a tab page based off of a bool. There is a bindable property in the XAML called "IsVisible", which I assumed would hide the tab from the user, but instead the tab still shows but displays a blank page when selected.
Currently my XAML looks like this
<?xml version="1.0" encoding="utf-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:local="clr-namespace:com.XXXXXXX"
prism:ViewModelLocator.AutowireViewModel="True"
BackgroundColor="White"
x:Class="com.XXXXXXXXXX.EditChargePage"
Title="{Binding Title}">
<local:EditChargeDetailsPage Title="Details" />
<local:EditChargeTrackingPage Title="Tracking" IsVisible="{Binding TabContext.HasTracking}" IsEnabled="{Binding TabContext.HasTracking}"/>
<local:EditChargeNotesPage Title="Notes" />
</TabbedPage>
Originally to solve the problem I just used "IsVisible", when that didn't work as expected I added "IsEnabled" which didn't seem to do anything.
Is there a way to hide the Tab from the UI using a boolean value in Xamarin (or Prism for Xamarin) without breaking MVVM?
You might want to check out the Prism Samples. The TabbedNavigation sample demonstrates how to initialize your tabbed children with INavigatingAware or the IEventAggregator, as well as dynamically adding the tabs at run time. If you need even finer control, such as a value in a ViewModel of one of your Child Pages that determines whether some other page should be shown, then you could use this to publish an event with the IEventAggregator and subscribe to that event in your TabbedPage to handle adding or removing the page.
Unfortunately IsVisible and IsEnabled do not actually work within a TabbedPage the way you were hoping. So the only way you can accomplish this is to actually manipulate the Children of the TabbedPage directly pushing or popping them from the collection.

Coding a Navigation Drawer Menu (Slider Menu). (Master Page Detail)

Trying to build a Slider menu I´m using this docu coming from official Xamarin.
MasterPageDetail
Quite odd, it´s not working. VS2015 intellense recognized me MasterDetailPage (my class is inheriting from it), but when I´m trying to launch the app, next error appears:
The type or namespace name 'MasterPageDetail' does not exist in the namespace 'Xamarin.Forms' (are you missing an assembly reference?)
What it happens? Do you know of any simply working demo?
I´m using this question as reference, but I´m not getting it works...
Slider
Some answer uses MasterPageDetail, another one implemented the solution in app (class) and I need to do it in a ContentPage
Thanks mates.
EDITED: I´m using Xamarin.Forms and I imported it and I don´t have any class called like this (MasterPageDetail)... Quite odd, it sounds like a stupid thing but I can´t see it.
MasterDetailPage is class from Xamarin.Forms if you have class with the same name then it may be a conflict.
Here are some useful links:
https://developer.xamarin.com/guides/xamarin-forms/user-interface/navigation/master-detail-page/
https://developer.xamarin.com/api/type/Xamarin.Forms.MasterDetailPage/
You can also download my Example from my Github:
https://github.com/15mgm15/XamarinForms-MasterDetailPage-Recipe
There's a simple way to create a MasterDetailPage using XAML, first of all you need to create a page which will contains the MasterDetailPage and a SecondPage which will contains a DetailPage, by doing this, you need to change your hierarchy of this page to MasterDetailPage, and finally load a SecondPage inside of MasterDetailPage.
In your project Create a New Page - MenuPage and change the Page Type ContentPage to MasterDetailPage
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
BackgroundColor="White"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourProject.MenuPage">
</MasterDetailPage>
Then go to your MenuPage.cs and change the hierarchy to MasterDetailPage too.
public partial class MenuPage : MasterDetailPage
{
public ChatPage()
{
InitializeComponent();
}
}
Go back to your XAML page - MenuPage and add this :
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourProjectName.MenuPage">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<StackLayout Orientation="Vertical">
<!--Here goes your Menu Items-->
<Button Text="MyFirstButton"/>
<Button Text="MySecondButton"/>
<Button Text="MyThirdButton"/>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<local:SecondPage/>
</MasterDetailPage.Detail>
</MasterDetailPage>
And finally you need to add a reference to your DetailPage
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourProjectName.MenuPage"
<!-- Add this line to refer your DetailPage, `SecondPage`-->
<!-- put your namespace and repeat in assembly -->
xmlns:local="clr-namespace:YourProjectName;assembly=YourProjectName">
</MasterDetailPage>
I hope its helps you!
I got it.
Finally I clean all project and started a code from zero using the next example (adding just MasterPageItem.cs, piece of cake):
Working MasterDetailDemo
I improved the demo by my own, creating a Master Page Detail where Master´s items bind specific generic page, it will be fill with its own attributes whose depends of id passed to the page´s constructor.
Github Slider Menu improved demo
Hoping it helps...

Categories