ListView navigation using Xamarin.Forms Shell - c#

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.

Related

Setting my partial View, not working xamarin

Now I got started with Prism Framework for xamarine, but I'm having a little problem achieving connections across views.
I have this folder "Views" and inside it I have another folder called PartialViews. Now inside PartialViews I have a contentPage called "Header.xaml".
Now I would like to atach this file to the Index.xaml view, which is located in the Views folder. I would like to atach the "Header.xaml" to other views also, like for example I would like to atach it to the "Orders.xaml" view.
My Header.xaml file is as follows :
<?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:prism="http://prismlibrary.com"
xmlns:local="clr-namespace:PROJECTX.Views"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="PROJECTX.Views.Header">
<StackLayout>
<Label Text="Trying partial views" />
</StackLayout>
</ContentPage>
While my Index.xaml is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:combobox="clr-namespace:Syncfusion.XForms.ComboBox;assembly=Syncfusion.SfComboBox.XForms"
xmlns:ListCollection="clr-namespace:System.Collections.Generic;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
xmlns:local="clr-namespace:PROJECTX.Views"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="PROJECTX.Views.Index"
x:Name="selfi">
<ScrollView>
<local:Header mvvm:ViewModelLocator.AutowirePartialView="{x:Reference selfi}" />
<combobox:SfComboBox x:Name="comboBox">
<combobox:SfComboBox.ComboBoxSource>
<ListCollection:List x:TypeArguments="x:String">
<x:String>Rendit sipas: Me te kerkuara</x:String>
<x:String>Rendit sipas: Te fundit</x:String>
<x:String>Rendit sipas: Alfabetit</x:String>
</ListCollection:List>
</combobox:SfComboBox.ComboBoxSource>
</combobox:SfComboBox>
</ScrollView>
</ContentPage>
I also registred on my App.xaml.cs the routing of the PartialViews folder with the view model like this:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
containerRegistry.RegisterForNavigation<Index, IndexViewModel>();
//containerRegistry.RegisterForNavigation<Header, HeaderViewModel>();
ViewModelLocationProvider.Register<Header, HeaderViewModel>();
}
Now I get a few errors...
1. The property 'Content' is set more than once.
2. The attachable property 'AutowirePartialView' was not found in type 'ViewModelLocator'.
3. Property 'Content' does not support values of type 'Header'.
Now I know this might be a rookie question, but I just can't seem to get it to work this partial views thing.
Is my understanding of partial views in xamarin correct? I'm supposed to call the partial view from the view.. correct?
Any help I would really really appreciate.
So you have to understand that in Xamarin forms, you can only have one ContentPage object for a page, hence you are getting the error “Content is set more than once”. You can however have multiple Layouts inside a single page
Here’s a quick snippet explaining pages versus layouts
Since you’re looking to use the Prism "PartialViews", a common way of referencing them is a "Template". So you’d have a HeaderTemplate file as you have shared. But instead of a ContentPage object, you would use a ContentView object (which is of type Layout) and you would define the content of the header inside that. (Official Docs)
And then you can add it to any page using this line inside your XAML as you would add a regular layout:
<templates: HeaderTemplate/>

Best practice for choosing handler or command for the button in Xamarin.Forms

I'm new in Xamarin. By learning the MVVM pattern, I've got the idea for mapping button with commands, and deal with logical things in viewmodel.
Then scenarios changed.
When I was developing some Login functionalities for the mobile app, I need to call "DisplayAlert" or "pop" or "push" when clicking the button.
I checked some forums and blogs to see how to solve, listed as below:
pass the navigation as a parameter, like this thread, or even use injection in the same thread;
use NuGet packages like userdialogs
use handler like Microsoft docs, (so I assumed that it is acceptable to use handler in simple navigation).
add some message text in viewmodel class and mapping to some entries on the view, but this cannot solve the conflict when it is required for a dialog box or navigation.
So is this question supposed to change to "how to choose button implementation, handler or command"?
But again, "handler" is not recommended by MVVM. Now I am confused.
Any advice will be helpful.
Cheers.
Though you have used MVVM .Use command is better because it will break the standard of MVVM (we should handle the logic in ViewModel as soon as possible) if you use click event in code behind.
You can handle the logic in ViewModel and pass params in xaml .
For example , if you want pass the content page and get the navigation in ViewModel
in xaml
<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"
x:Name="MainContentPage"
x:Class="xxx.MainPage">
//...
<Button Command="{Binding Path=BindingContext.ButtonClickCommand , Source={x:Reference MainContentPage}}" CommandParameter="{Binding .}" Text="xxx"/>
...
in ViewModel
ButtonClickCommand = new Command(
(parameter) =>
{
var page = parameter as ContentPage;
// do something you want
});

SlideOverKit : A value of type 'SlideMenuView' cannot be added to a collection or dictionary of type 'IList'

I am implementing BottomSheet in Xamarin.forms with the help of SlideOverKit library available in NuGet Gallery. I have referred their sample available on GitHub. My implementation details are bellow
Implementation details:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SmartApp.CustomControls"
xmlns:y="clr-namespace:SlideOverKit;assembly=SlideOverKit"
Title="Opportunities"
x:Class="SmartApp.OpportunitiesPage">
<TabbedPage.ToolbarItems>
<!--Menu Item here-->
</TabbedPage.ToolbarItems>
<ContentPage Title="Tab 1" >
<!--Tab 1 details here-->
</ContentPage>
<y:SlideMenuView >
<!--Tab 2 details here-->
</y:SlideMenuView>
</TabbedPage>
In the above implementation I am facing on compile time error which is "A value of type 'SlideMenuView' cannot be added to a collection or dictionary of type 'IList'", also y:SlideMenuView not having support for Title attribute which is another issue. How can I resolve this issue? please help.
The SlideMenuView must be placed within a MenuContainerPage instead of a ContentPage.
See their sample in c#. The same can also be done in XAML:
Simply replace your ContentPage with a y:MenuContainerPage or create a custom page that inherits from MenuContainerPage and use that as parent page.
This information can also be found on their website:
Inherit
The page which contains SlideMenuView must inherit from
MenuContainerPage or IMenuContainerPage. Your page can inherit from
MenuContainerPage, so that you can just set SlideMenuView property and
it will get work.
If your page need to inherit from other base pages in your solution,
you must implement IMenuContainerPage interface and you need to create
the renderer pages for each platforms. It won't too hard, just copy
codes from sample, you can follow the SlideDownMenuPage page in sample
code to do this.

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.

Prism Xamarin Forms Tabbed Page Navigation

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?

Categories