Add Shell Navigation templates for various pages Xamarin.Forms Shell - xamarin

I have multi-page app, which has preLogin section and postLogin section.
Which is the best approach to make shell templates for these two sections?
preLogin pages doesnt have backbutton in navigationBar. I tried in xaml page NavigationPage.HasNavigationBar="false" (not AppShell.xaml, either in my page xaml) as well as in code behind NavigationPage.SetHasNavigationBar(this, false);
example xaml page which regardless on my NavigationPage.HasBackButton="false"
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:customViewEntry="clr-namespace:App.CustomViews.Entries"
xmlns:header="clr-namespace:App.CustomViews.CustomHeaders"
mc:Ignorable="d"
x:Class="App.Views.Login.EnterEmailAndPasswordPage"
NavigationPage.HasBackButton="false"
BackgroundImageSource="Login_Screen_Green.png">
<ContentPage.Content>
<StackLayout>
<header:HeaderWithTopRightIcon ImageUri="greenIcon.png"/>
<StackLayout VerticalOptions="EndAndExpand" Padding="0,50">
<customViewEntry:EvEntry
Placeholder="Enter your email"/>
<customViewEntry:EvEntry
Placeholder="Enter your password"
IsPassword="True"/>
<Button
Text="LOGIN"
Margin="25,0"
CornerRadius="7"
BackgroundColor="{StaticResource DarkGrayColor}"
TextColor="White"
Command="{Binding OpenEmailVerificationPageCommand}"/>
<Label
Padding="0,25,0,0"
Text="Don't have an account?"
FontSize="Small"
Style="{StaticResource WhiteSmallLabelStyle}"
HorizontalOptions="Center"
VerticalOptions="Start"/>
<Label
Text="SIGN UP"
TextDecorations="Underline"
FontSize="Small"
Style="{StaticResource WhiteSmallBoldLabelStyle}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SignUpClickCommand}"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
my AppShell looks like:
<?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"
mc:Ignorable="d"
xmlns:views="clr-namespace:App.Views"
xmlns:loginViews="clr-namespace:App.Views.Login"
x:Class="App.AppShell"
FlyoutBehavior="Disabled">
<!--Styles and Resources-->
<Shell.Resources>
<ResourceDictionary>
...removed due simplicity...
</ResourceDictionary>
</Shell.Resources>
<ShellContent ContentTemplate="{DataTemplate loginViews:EnterEmailPage}"/>
</Shell>
So, my questions are
1. How to dynamically hide back button on some pages and on some not? For navigation Im using await Shell.Current.GoToAsync(route)
2. Also I need a redirection when user leaves application, and again enter it based on elapsed time, to redirect to preLogin page (login) or to let him directly to postLogin (full access to the app) so I need maybe two AppShell classes, and to call it different shells OnResume() ?

How to dynamically hide back button on some pages and on some not? For navigation Im using await Shell.Current.GoToAsync(route)
About this question , here is a Workaround for you .
Shell application has Back button behavior to ovveride Back Button dynamically , even can Hide/Show it .
If using Shell.Current.GoToAsync(route) to navigate to destination page , you can follow the below code to use in your destination page.
// Button click to show Back Button
private void Button_Clicked_Show(object sender, EventArgs e)
{
Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
IsEnabled = true
});
}
// Button click to hide Back Button
private void Button_Clicked_Hide(object sender, EventArgs e)
{
Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
IconOverride = "null.png", // null.png not exists in project ,just want
the program to show a blank Back button
IsEnabled = false
});
}
I will show the effect with a Gif :
Also I need a redirection when user leaves application, and again enter it based on elapsed time, to redirect to preLogin page (login) or to let him directly to postLogin (full access to the app) so I need maybe two AppShell classes, and to call it different shells OnResume() ?
About this question , here is a Suggestion for you , you can conside that whether fit your needs .
You can use Navigation.PushModalAsync(new LoginPage()) to redirect to preLogin page based on elapsed time . Otherwise using Shell.Current.GoToAsync(route) to Navigate . You can deal with them in OnResume Method .
For example as follow :
protected override void OnResume()
{
if(time > xxx)
{
Navigation.PushModalAsync(new LoginPage());
}
else
{
Shell.Current.GoToAsync(route);
}
}
Here using PushModalAsyncto Login Page that is a Model Page . After using Navigation.PopModalAsync() can dismiss LoginPage and redirect to other Page with Shell.Current.GoToAsync(route).

Related

How can programmatically change from Light Mode to Dark Mode in Xamarin.Forms Android and / or programmatically change the color of the scroll bar?

I want to allow my user to select the AppTheme as he wants. Following are the options I want to give :-
Automatic (As per the user selection in Settings).
Light Mode
Dark Mode
I found a solution to use the below code:-
if(theme == App.Theme.Light)
{
Delegate.SetLocalNightMode(AppCompatDelegate.ModeNightNo);
} else
{
Delegate.SetLocalNightMode(AppCompatDelegate.ModeNightYes);
}
But this code recreates the entire activity and on the click on the button, I am again taken to the LoginPage of my App.
Can anyone suggest me a way to programmatically change from Light Mode to Dark Mode in Xamarin.Forms Android?
Also does anyone know another way that I could programmatically change the color of the scroll bar.
Have two style files Light and Dark XAML and ThemeHelper class which switches the themes at run time
Refer this https://github.com/jamesmontemagno/Hanselman.Forms/tree/vnext/src/Hanselman/Styles
Update
As mentioned this sample project has great resources for theme switching.
Light Theme
<?xml version="1.0" encoding="UTF-8" ?>
<ResourceDictionary
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestApp.LightTheme">
<Color
x:Key="TextColor">#ababab</Color>
<Color
x:Key="GenericBackground">#e3e3e3</Color>
<Color
x:Key="AppBackground">#FFFFFF</Color>
</ResourceDictionary>
Dark theme
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestApp.DarkTheme">
<Color
x:Key="TextColor">#e3e3e3</Color>
<Color
x:Key="GenericBackground">#ababab</Color>
<Color
x:Key="AppBackground">#000000</Color>
</ResourceDictionary>
ThemeHelper
public class ThemeHelper
{
public static Theme CurrentTheme = Theme.Light;
public static void ChangeTheme(Theme theme, bool forceTheme = false)
{
// don't change to the same theme
if (theme == CurrentTheme && !forceTheme)
return;
//// clear all the resources
var applicationResourceDictionary = Application.Current.Resources;
ResourceDictionary newTheme;
if (theme == Theme.Default)
{
theme = AppInfo.RequestedTheme == AppTheme.Dark ? Theme.Dark : Theme.Light;
}
switch (theme)
{
case Theme.Light:
newTheme = new LightTheme();
break;
case Theme.Dark:
newTheme = new DarkTheme();
break;
case Theme.Default:
default:
newTheme = new LightTheme();
break;
}
ManuallyCopyThemes(newTheme, applicationResourceDictionary);
CurrentTheme = theme;
var background = (Color)App.Current.Resources["AppBackground"];
}
static void ManuallyCopyThemes(ResourceDictionary fromResource, ResourceDictionary toResource)
{
foreach (var item in fromResource.Keys)
{
toResource[item] = fromResource[item];
}
}
}
Theme enum
public enum Theme
{
Default,
Light,
Dark
}
Before starting the app initialize theme , you can retrieve it from Application settings or from DB like SQLite or API too
public App()
{
InitializeComponent();
ThemeHelper.ChangeTheme(Theme.Default);
MainPage = new NavigationPage(new MainPage());
}
Make sure you use DynamicResource in this approach
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
BackgroundColor="{DynamicResource AppBackground}"
x:Class="TestApp.MainPage">
<ContentPage.ToolbarItems>
<ToolbarItem
Text="Default"
Clicked="ToolbarItem_Clicked" />
<ToolbarItem
Text="Light"
Clicked="ToolbarItem_Clicked_1" />
<ToolbarItem
Text="Dark"
Clicked="ToolbarItem_Clicked_2" />
</ContentPage.ToolbarItems>
<StackLayout>
<Label
Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
TextColor="{DynamicResource TextColor}"
BackgroundColor="{DynamicResource GenericBackground}" />
<Label
x:Name="label"
TextColor="{DynamicResource TextColor}"
BackgroundColor="{DynamicResource GenericBackground}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Screenshot
You may still need some changes in Android with respect to different API levels.
Other reference
Theming
Dark mode detection
Android Dark Theme
You can use DynamicResources for implement dynamic theme functionality without redirection. You can follow these documents.

MasterDetail with Prism, how to?

I am trying to test and example with MasterDetail. You can see the code in:
https://github.com/jrariasf/MD8/tree/master/MD8
The Master have 5 buttons to access to 4 detail pages (Home, MainPage, ViewA, ViewB and ViewC).
From ViewA, with 2 buttons I am able to load ViewB and ViewC
But I am not able to do that pushing a button in hambubrger menu then load the detail page adequated.
It only works if I put an absolute path in the CommandParameter in "PrismMasterDetailPage.xaml":
<?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:prism="http://prismlibrary.com"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="MD8.Views.PrismMasterDetailPage">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<StackLayout Padding="20">
<!-- TODO: // Update the Layout and add some real menu items -->
<Button Text="Home" Command="{Binding NavigateCommand}" CommandParameter="/PrismMasterDetailPage/NavigationPage/ViewA" />
<Button Text="MainPage" Command="{Binding NavigateCommand}" CommandParameter="/NavigationPage/MainPage" />
<Button Text="ViewA" Command="{Binding NavigateCommand}" CommandParameter="../ViewA" />
<Button Text="ViewB" Command="{Binding NavigateCommand}" CommandParameter="./ViewB" />
<Button Text="ViewC" Command="{Binding NavigateCommand}" CommandParameter="ViewC" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
</MasterDetailPage>
Then, in "PrismMasterDetailPageViewModel.cs"
void ExecuteCommandName(string page)
{
Console.WriteLine("PrismMasterDetailPageViewModel - ExecuteCommandName() Vamos a {0}", page);
_navigationService.NavigateAsync(page);
}
If I am in "/PrismMasterDetailPage/NavigationPage/ViewA", what I have to do to unload ViewA and load ViewB ?
For example, in App.xaml.cs the code is:
await NavigationService.NavigateAsync("PrismMasterDetailPage/NavigationPage/ViewA");
Then, execute the app on android emulator, push buttons of hamburger menu and the result it is not as I expected.
Pressing Home button, the _navigationService.GetNavigationUriPath() returns: /PrismMasterDetailPage/NavigationPage/ViewA/NavigationPage?useModalNavigation=true/ViewA
why?
If I press button ViewA or ViewB or ViewC, it don't show anything. But the OnNavigatedFrom() method is called on each View*ViewModel.cs
What is wrong?
Thanks!!
One fo the first things you need to do is understand where you are Navigating from. Navigation in Xamarin.Forms is very dependent on where you are Navigating from. Remember that without Prism you would do something like this:
var mdp = new MyMasterDetailPage
{
Detail = new NavigationPage(new ViewA)
};
In order to achieve a Hamburger Menu with Prism you typically would want a MasterDetailPage as the Application's Main Page. The next segment in the Navigation Uri must be a NavigationPage and the following page would generally be a ContentPage.
<Button Text="Home"
Command="{Binding NavigateCommand}"
CommandParameter="/PrismMasterDetailPage/NavigationPage/ViewA" />
Ok so looking at this first one, this is generally what you would use when navigating from the PrismApplication which is why it works.
<Button Text="MainPage"
Command="{Binding NavigateCommand}"
CommandParameter="/NavigationPage/MainPage" />
Looking at this one, this is really close to what you do want except you are doing an absolute navigation which means that you are resetting the Application.MainPage. What you actually need is a relative Uri because you are navigating from the MasterDetailPage.
<Button Text="ViewA"
Command="{Binding NavigateCommand}"
CommandParameter="../ViewA" />
This is completely wrong because ../{path} is only supported from within a NavigationPage and you are in a MasterDetailPage...
<Button Text="ViewB"
Command="{Binding NavigateCommand}"
CommandParameter="./ViewB" />
This is just not supported by Prism at all.
<Button Text="ViewC"
Command="{Binding NavigateCommand}"
CommandParameter="ViewC" />
This is setting the MasterDetailPage.Detail like:
mdp.Detail = new ViewC()
Of course as I mentioned above you need it to be
mdp.Detail = new NavigationPage(new ViewC());
Thanks a lot Dan Siegel ! (#Dan S.)
I have just seen your comment, a month ago, sorry.
I was a newbie in C# and Xamarin and Prism and I am still a newbie but less :-)
I have learnt and tested a lot in the last weeks and I understand better the concepts.
After reading you I know that ../{path} is only valid with a NavigationPage .
Futhermore, one problem I had was thar I was checking the value of "_navigationService.GetNavigationUriPath()" inside OnNavigatedTo method and as I read later, at that moment the UriPath is not the real final UriPath.
In my code I wrote:
public void OnNavigatedTo(INavigationParameters parameters)
{
Console.WriteLine("DEBUG - ViewAVM: We are in {0}",
_navigationService.GetNavigationUriPath());
}
I moved the GetNavigationUriPath() call to another method and the results were as I expected.
Thanks!!

How can I create a template / class that will allow me to simplify some my Xaml where there are multiple elements into just one?

Here's an example of what I need to do now. Sometimes I have one span, sometimes more.
Note that this post is similar to that of another question. For the other question I had only one comment to use a custom control with no more advice offered and one answer to use JavaScript. I tried to add a second bounty to that question but it gave me the option of only adding a bounty of 500 points. The question is now so old that I doubt anyone will see it any more and as I cannot add a bounty (unless it's 500 points) I cannot give it more visibility.
Here's what I would like to simplify:
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Hello " />
<Span Text="Hello " />
<Span Text=" Some more text." />
</FormattedString>
</Label.FormattedText>
</Label>
Here's what I would like to do instead of typing in <Label><Label.FormattedText><FormattedString> I would like to get some way to do this with only entering in <template:FormattedLabel>
<template:FormattedLabel>
<Span Text="Hello " />
<Span Text="Hello " />
<Span Text=" Some more text." />
</template:FormattedLabel>
or
<template:FormattedLabel>
<Span Text="Hello " />
</template:FormattedLabel>
Note that I have looked into custom controls but as far as I see I cannot find a way to make these accept some inside content which in this case would be one or more spans.
I have an example of something similar which could perhaps be used but I am not sure how to apply it. What I was hoping for was a template like this in the XAML below which is does something similar to what I need but for content pages:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Japanese;assembly=J"
xmlns:t="clr-namespace:J.Templates"
x:Class="Japanese.Templates.ContentScrollable"
x:Name="ContentPage" >
<ContentPage.Content>
<t:Stack Orientation="Vertical">
<ScrollView x:Name="scroll">
<ContentView Content="{Binding Source={x:Reference ContentPage}, Path=InnerContent}"
Margin="{DynamicResource PageMargin}" />
</ScrollView>
</t:Stack>
</ContentPage.Content>
</ContentPage>
With its C# back end:
public partial class ContentScrollable : ContentPage
{
public static readonly BindableProperty InnerContentProperty = BindableProperty.Create(nameof(InnerContent), typeof(View), typeof(ContentScrollable));
public View InnerContent
{
get => (View)this.GetValue(InnerContentProperty);
set => this.SetValue(InnerContentProperty, value);
}
public ContentScrollable()
{
InitializeComponent();
}
}
How can I accomplish what I am looking for?
You can do the following:
<!-- FormattedLabel.xaml -->
<?xml version="1.0" encoding="UTF-8"?>
<Label
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourNamespaceForTemplates.FormattedLabel" />
// FormattedLabel.xaml.cs
[ContentProperty(nameof(Spans))]
public partial class FormattedLabel : Label
{
private readonly ObservableCollection<Span> _spans;
public IList<Span> Spans => _spans;
public FormattedLabel()
{
_spans = new ObservableCollection<Span>();
_spans.CollectionChanged += OnSpansChanged;
InitializeComponent();
}
private void OnSpansChanged(object sender, NotifyCollectionChangedEventArgs e)
{
FormattedText?.Spans?.Clear();
FormattedText = FormattedText ?? new FormattedString();
Spans.ForEach(FormattedText.Spans.Add);
}
}
Basically, in this extension of Label we define the content to be a list of Span items, which will allow you to define them in XAML inside <FormattedLabel></FormattedLabel>. To make it work, we pass these items down to this.FormattedText.Spans.
To use it:
<template:FormattedLabel>
<Span Text="Hello " />
<Span Text="Hello " />
<Span Text=" Some more text." />
</template:FormattedLabel>
I have just checked it and it works perfectly. I hope this helps!

Hamburger menu not showing on iOS . Prism issue, Xamarin issue or my issue

I am trying to implement a masterDetail app with hamburger menu.
It works in android but crashes on iOS with "FileNotFoundException" and shows default instead the icon.
I have added an icon to iOS. Resources project but still does not show and both the master and navigation page have the icon.
Am I doing something wrong?
Any workaround?
thanks a lot
app.xaml
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override void OnInitialized()
{
try
{
InitializeComponent();
NavigationService.NavigateAsync("MainMasterDetail/MyNavigationPage/MainPage",animated:false);
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
protected override void RegisterTypes()
{
Container.RegisterTypeForNavigation<MainMasterDetail,MainMasterDetailViewModel>();
Container.RegisterTypeForNavigation<MyNavigationPage,MyNavigationPageViewModel>();
Container.RegisterTypeForNavigation<MainPage>();
Container.RegisterTypeForNavigation<ViewA,ViewAViewModel>();
Container.RegisterTypeForNavigation<ViewB,ViewBViewModel>();
}
}
MainMasterDetails.xaml
<?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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="HelloBurgerMenu.Views.MainMasterDetail"
Title="MainMasterDetail" Icon="humburger.png">
<MasterDetailPage.Master>
<ContentPage Title="Default">
<StackLayout>
<Button Text="MainPage" Command="{Binding NavigateCommand}" CommandParameter="MyNavigationPage/MainPage" />
<Button Text="ViewA" Command="{Binding NavigateCommand}" CommandParameter="MyNavigationPage/ViewA" />
<Button Text="ViewB" Command="{Binding NavigateCommand}" CommandParameter="MyNavigationPage/ViewB" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
</MasterDetailPage>
MyNavigationPage
<?xml version="1.0" encoding="utf-8" ?>
<NavigationPage 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"
x:Class="HelloBurgerMenu.Views.MyNavigationPage"
Icon="humburger.png">
</NavigationPage>
Try specify the Icon in MasterPage not MasterDetail
public MasterPage()
{
InitializeComponent();
if (Device.RuntimePlatform == Device.iOS)
{
Icon = "menu.png";
}
}
You can't have content in your NavigationPage. Delete all the XAML in your NavigationPage.
Look at this sample: https://github.com/xamarin/xamarin-forms-samples/tree/master/Navigation/MasterDetailPage

Xamarin.Forms - Is there a mechanism to "include" a partial view?

Does Xamarin.Forms have a concept of includes?
I'm creating an app that has a shared header across all pages. Is there a way to create the header once and include it on all pages? Better yet, is there a way to create a template or a reusable layout that you can put all content inside for each page? It would be a similar concept to .NET MVC's _Layout file.
What you need is the ControlTemplate introduced in 2.1.0.
Create a control template in your ResourceDictionary in Application.Resources.
<?xml version="1.0" encoding="utf-8" ?>
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.App">
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="MainPageTemplate">
<StackLayout>
<Label Text="Header Content" FontSize="24" />
<ContentPresenter />
</StackLayout>
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
Then in your ContentPage, assigned the ControlTemplate
<?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="Mobile.MainPage"
ControlTemplate="{StaticResource MainPageTemplate}">
<Label Text="Main Page Content" FontSize="18" />
</ContentPage>
Then you end up with
Referenced from: http://www.xamarinhelp.com/xamarin-forms-page-templates/
Yes. You can use User Controls for this. You can Use XAML or code only. I'll explain the XAML way.
Just add a new XAML Page and change the root type from ContentPage to StackLayout. The root type can be every other layout or control. You have to decide what fits best.
MyControl.xaml
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App6.MyControl">
<Label Text="{Binding Name}" />
<Label Text="{Binding Age}" />
<Label Text="{Binding CatAmount}" />
</StackLayout>
We bind the properties Name, Age, CatAmount to three different labels. We assume, that the BindingContext of this control is an object of type PersonData (see below).
In your Code behind, you have to change the type as well.
MyControl.xaml.cs
public partial class MyControl : StackLayout
{
public MyControl()
{
InitializeComponent();
}
}
In your page, you have to add a new namespace (e.g. local that points to you assembly, e.g. App6 or MyApp.Whatever). Then you can use it via local:MyControl. In our example control, we bind the BindingContext to Person, wich is a Property of our Page's BindingContext, that is (in our case) the page itself. If your control is in a sub namespace, you have to change the namespace part accordingly.
Page2.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"
xmlns:local="clr-namespace:App6;assembly=App6"
x:Class="App6.Page2">
<local:MyControl BindingContext="{Binding Person}"></local:MyControl>
</ContentPage>
Page2.xaml.cs
public class PersonData
{
public string Name { get; set; }
public int Age { get; set; }
public int CatAmount { get; set; }
}
public partial class Page2 : ContentPage
{
public PersonData Person { get; set; }
public Page2()
{
Person = new PersonData {Age = 28, Name = "Sven", CatAmount = 2};
InitializeComponent();
BindingContext = this;
}
}
And in your mentioned Scenario, you can simply inherit from ContentPage and add your common elements and use you inherited Page as base class of your pages.
TemplatedPage - Xamarin.Forms 2.1
With Xamarin.Forms 2.1 they introduced TemplatedPage. You find the example here: http://xfcomplete.net/general/2016/01/20/control-templates/ . The LoginView example with the ContentPresenter fits your scenario exactly.

Resources