How to bind and get word of resx (localization) - xamarin

I followed this article: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/localization/text?pivots=macos
I want to bind and get a value of my .resx
Title="{x:Static resx:AppResources.Binding Title}">
their value of title is Road, Fly, Run from my ViewModel
<data name="Road" xml:space="preserve">
<value>Camino</value>
</data>

I have checked that in local site as follow steps , and it works .
Creat a AppResources.resx file :
<data name="Fly" xml:space="preserve">
<value>DefaultFlyRoute</value>
</data>
<data name="Road" xml:space="preserve">
<value>DefaultRoad</value>
</data>
<data name="Run" xml:space="preserve">
<value>DefaultRunRoute</value>
</data>
In ViewModel class to load .resx data as default value when initialiation .
public class ViewModel
{
public string Road { get; set; }
public string Fly { get; set; }
public string Run { get; set; }
public ViewModel()
{
Road = AppResources.Road;
Fly = AppResources.Fly;
Run = AppResources.Run;
}
}
The Xaml code as follow to bind value from ViewModel :
<?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:local="clr-namespace:AppResxFile"
mc:Ignorable="d"
x:Class="AppResxFile.MainPage">
<ContentPage.BindingContext>
<local:ViewModel />
</ContentPage.BindingContext>
<StackLayout>
<!-- Place new controls here -->
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Label Text="{Binding Road}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Label Text="{Binding Fly}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Label Text="{Binding Run}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
The final effect as follow :

Related

How to open a page from a class?

I am trying to create a little application using MVVM. I would like to open a second page that scan a QR code and then back the value of the QR code to the main page.
I have this code:
Main view:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="QRScannerXamarinForms.Views.MainPageView"
xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
xmlns:vm="clr-namespace:QRScannerXamarinForms.ViewModels">
<ContentPage.BindingContext>
<vm:MainPageViewModel/>
</ContentPage.BindingContext>
<StackLayout>
<Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
<Label Text="Barcode Sample" HorizontalTextAlignment="Center" TextColor="White" FontSize="36" />
</Frame>
<Button x:Name="ucBtnEscanear" Text="Escanear"
Command="{Binding EscanearCommand}"/>
</StackLayout>
</ContentPage>
Main view model:
private INavigationService _navigationService;
public ICommand EscanearCommand { get; private set; }
private void Escanear()
{
string miCodigoQr = _navigationService.AbrirPaginaEscaner();
}
Second view:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="QRScannerXamarinForms.Views.ScannerView"
xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
xmlns:vm="clr-namespace:QRScannerXamarinForms.ViewModels">
<ContentPage.BindingContext>
<vm:ScannerViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
<Label Text="Barcode Sample" HorizontalTextAlignment="Center" TextColor="White" FontSize="36" />
</Frame>
<Label x:Name="ucScanResultText" />
<zxing:ZXingScannerView x:Name="ucZXingScannerView" IsScanning="True" IsAnalyzing="True" Result="{Binding CodigoQr}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Second view model:
class ScannerViewModel : BaseViewModel
{
private string _codigoQr;
public string CodigoQr
{
get { return _codigoQr; }
set { _codigoQr = value; }
}
}
Interface to open pages:
namespace QRScannerXamarinForms.Services
{
interface INavigationService
{
string AbrirPaginaEscaner();
}
}
Implementation of the interface that allows navigation.
namespace QRScannerXamarinForms.Services
{
class ViewNavigationService : INavigationService
{
public string AbrirPaginaEscaner()
{
ScannerView miScannerView = new ScannerView();
ScannerViewModel miScannerViewModel = miScannerView.BindingContext as ScannerViewModel;
Application.Current.MainPage.Navigation.PushModalAsync(miScannerView);
return miScannerViewModel.CodigoQr;
}
}
}
But in the implementation of the interface, the second page is not shown. So this line doesn't work:
Application.Current.MainPage.Navigation.PushModalAsync(miScannerView);
How could I open from this class?
Thanks.

Xamarin, custom control with layout with accepts bindable content at a specific location

I need to create a standard layout which I can use on a number of pages, but pass in content which is shown inside... I'm having limited success...
Here's how I'm calling the custom control...
<?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:control="clr-namespace:myApp"
x:Class="myApp.MainPage">
<StackLayout>
<control:CustomPopupLayoutControl
BackgroundColor="LightGreen">
<control:CustomPopupLayoutControl.Content>
<Button Text="Hello" />
<!-- lots of other controls, buttons, labels etc, layout -->
</control:CustomPopupLayoutControl.Content>
</control:CustomPopupLayoutControl>
</StackLayout>
</ContentPage>
So you can see here I wan't to display some content..
Here's my custom control...
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="myApp.CustomPopupLayoutControl"
x:Name="CustomPopupLayouts">
<ContentView.Content>
<StackLayout BackgroundColor="LightBlue" Margin="30">
<Button Text="Close" /><!-- important-->
<!-- lots of other layout -->
<StackLayout BackgroundColor="Red" x:Name="Inner">
</StackLayout>
</StackLayout>
</ContentView.Content>
</ContentView>
So I'd like to show my hello button inside the Inner stack layout, I'll also need binding to work...
So the final page should look like...
<page>
<StackLayout BackgroundColor="LightBlue" Margin="30">
<Button Text="Close" /><!-- important-->
<StackLayout BackgroundColor="Red">
<button text="Hello">
</StackLayout>
<StackLayout>
</page>
Since you had defined a Button in Custom Control , You just need to pass the Title that you want to display on the Button from ContentPage to Custom Control.
in CustomPopupLayoutControl.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"
x:Class="myApp.CustomPopupLayoutControl"
x:Name="CustomPopupLayouts">
<ContentView.Content>
<StackLayout BackgroundColor="LightBlue" HeightRequest="450" Margin="30">
<Button HeightRequest="150" WidthRequest="80" Text="{Binding Source={x:Reference CustomPopupLayouts}, Path=ButtonTitle}" /><!-- important-->
<StackLayout BackgroundColor="Red" HeightRequest="300" x:Name="Inner">
</StackLayout>
</StackLayout>
</ContentView.Content>
</ContentView>
in CustomPopupLayoutControl.xaml.cs
Define a bindable property
public static BindableProperty ButtonTitleProperty =
BindableProperty.Create(nameof(ButtonTitle), typeof(string), typeof(CustomPopupLayoutControl),string.Empty);
public string ButtonTitle
{
get => (string)GetValue(ButtonTitleProperty);
set => SetValue(ButtonTitleProperty, value);
}
in ContentPage
You could set the title of button directly or use data binding .
<control:CustomPopupLayoutControl ButtonTitle = "Hello World!" BackgroundColor="LightGreen" / >
I've found a solution :)
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="myapp.CustomPopupLayoutControl"
x:Name="CustomPopupLayouts">
<ContentView.ControlTemplate>
<ControlTemplate>
<StackLayout BackgroundColor="LightBlue" Margin="30">
<Frame CornerRadius="5" Margin="20" HasShadow="False"
BackgroundColor="Red">
<StackLayout>
<Button Text="Close"
Command="{TemplateBinding
Parent.BindingContext.NavigateCommand}" />
<!-- important-->
<ContentPresenter />
</StackLayout>
</Frame>
</StackLayout>
</ControlTemplate>
</ContentView.ControlTemplate>
</ContentView>
.
<?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:control="clr-namespace:myapp"
x:Class="myapp.MainPage">
<StackLayout>
<control:CustomPopupLayoutControl BackgroundColor="LightGreen">
<StackLayout>
<Button Text="Hello" Command="{Binding NavigateCommand}" />
<Button Text="Goodbye" />
</StackLayout>
</control:CustomPopupLayoutControl>
</StackLayout>
</ContentPage>

How to share View Model between pages?

I can add data to the viewmodel, but when I try to access the same viewmodel from another page, the data is lost. How can I use the same viewmodel across multiple pages?
ViewModel Code
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;
namespace App1
{
class DebtViewModel
{
ObservableCollection<Debt> _Debt = new ObservableCollection<Debt>();
public System.Windows.Input.ICommand AddAccountCommand => new Command(AddAccount);
public System.Windows.Input.ICommand RemoveAccountCommand => new Command(RemoveAccount);
public System.Windows.Input.ICommand UpdateAccountCommand => new Command(UpdateAccount);
public ObservableCollection<Debt> Debt { get; set; }
public string Account { get; set; }
public string SelectedAccount { get; set; }
public double AnnualPercentageRate { get; set; }
public decimal Amount { get; set; }
public decimal MonthlyPayment { get; set; }
public bool IntroductoryRate { get; set; }
public double IntroductoryPercentageRate { get; set; }
public int IntroductoryRange { get; set; }
public DebtViewModel()
{
ObservableCollection<Debt> Debts = _Debt;
}
public void AddAccount()
{
var debt = new Debt(Account, Amount, AnnualPercentageRate, MonthlyPayment, IntroductoryRate,
IntroductoryPercentageRate, IntroductoryRange);
if (Account != null)
{
_Debt.Add(debt);
}
}
public void RemoveAccount()
{
//Debt.Remove(SelectedAccount);
}
public void UpdateAccount()
{
//int newIndex = Debt.IndexOf(SelectedAccount);
//Debt.Remove(SelectedAccount);
//Debt.Add(Account);
//int oldIndex = Debt.IndexOf(Account);
//Debt.Move(oldIndex, newIndex);
}
}
}
List Page
<?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:local="clr-namespace:App1"
mc:Ignorable="d"
x:Class="App1.ListViewPage">
<!-- Required to map viewmodel -->
<ContentPage.BindingContext>
<local:DebtViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add"></ToolbarItem>
</ContentPage.ToolbarItems>
<!-- Bind variable in view model to listview itemsource -->
<ContentPage.Content>
<StackLayout>
<!--<Entry Placeholder="Account"
Text="{Binding Account}"/>
<Button Text="Add" Command="{Binding AddAccountCommand}"></Button>
<Button Text="Remove" Command="{Binding RemoveAccountCommand}"></Button>
<Button Text="Update" Command="{Binding UpdateAccountCommand}"></Button>-->
<!--textcell, custom cells, or image cell-->
<ListView ItemsSource="{Binding Debt}" SelectedItem="{Binding SelectedAccount}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding AccountName}"
FontSize="Medium"
VerticalTextAlignment="Start"
Grid.Column="0"></Label>
<Label Text="Balance"
VerticalTextAlignment="Start"
Grid.Column="1"></Label>
<Label Text="{Binding InitialAmount}"
VerticalTextAlignment="End"
Grid.Column="1"></Label>
<Label Text="APR"
VerticalTextAlignment="Start"
Grid.Column="2"></Label>
<Label Text="{Binding AnnualPercentageRate}"
VerticalTextAlignment="End"
Grid.Column="2"></Label>
<Label Text="Monthly Payment"
VerticalTextAlignment="Start"
Grid.Column="3"></Label>
<Label Text="{Binding MonthlyPayment}"
VerticalTextAlignment="End"
Grid.Column="3"></Label>
<Image Source="edit.png" Grid.Column="4"></Image>
<Image Source="trash.jpg" Grid.Column="5"></Image>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Add Page
<?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:local="clr-namespace:App1"
mc:Ignorable="d"
x:Class="App1.ListViewPage">
<!-- Required to map viewmodel -->
<ContentPage.BindingContext>
<local:DebtViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add"></ToolbarItem>
</ContentPage.ToolbarItems>
<!-- Bind variable in view model to listview itemsource -->
<ContentPage.Content>
<StackLayout>
<!--<Entry Placeholder="Account"
Text="{Binding Account}"/>
<Button Text="Add" Command="{Binding AddAccountCommand}"></Button>
<Button Text="Remove" Command="{Binding RemoveAccountCommand}"></Button>
<Button Text="Update" Command="{Binding UpdateAccountCommand}"></Button>-->
<!--textcell, custom cells, or image cell-->
<ListView ItemsSource="{Binding Debt}" SelectedItem="{Binding SelectedAccount}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding AccountName}"
FontSize="Medium"
VerticalTextAlignment="Start"
Grid.Column="0"></Label>
<Label Text="Balance"
VerticalTextAlignment="Start"
Grid.Column="1"></Label>
<Label Text="{Binding InitialAmount}"
VerticalTextAlignment="End"
Grid.Column="1"></Label>
<Label Text="APR"
VerticalTextAlignment="Start"
Grid.Column="2"></Label>
<Label Text="{Binding AnnualPercentageRate}"
VerticalTextAlignment="End"
Grid.Column="2"></Label>
<Label Text="Monthly Payment"
VerticalTextAlignment="Start"
Grid.Column="3"></Label>
<Label Text="{Binding MonthlyPayment}"
VerticalTextAlignment="End"
Grid.Column="3"></Label>
<Image Source="edit.png" Grid.Column="4"></Image>
<Image Source="trash.jpg" Grid.Column="5"></Image>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
As Jason said: If you specify the VM in XAML it will create a new instance for each page. They are totally different.
How can I use the same viewmodel across multiple pages?
There are many ways to do it.
For example, you can define/create a static ViewModel in App.cs:
public partial class App : Application
{
public static DebtViewModel sharedViewModel { get; set; }
public App()
{
InitializeComponent();
MainPage = new MainPage();
createViewModel();
}
public void createViewModel() {
sharedViewModel = new DebtViewModel();
}
public class DebtViewModel {
}
}
Then in other page, you can set this ViewModel as page's bindingContext:
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
this.BindingContext = App.sharedViewModel;
}
}
Pass the instance to the new page on the constructor in also a solution.

Xamarin Forms TemplateBinding

I understand XAML doesn't really have a facility to extend (inherit) one page from another, but I have seen others use ControlTemplates to achieve this effect.
I am having trouble getting a Binding to work in this scenario. In my example, I have a base ContentPage extended by MainPage. Also, I am using FreshMVVM, so that is why the view model is minimal as FreshMVVM handles all the plumbing of property change notifications.
When the app runs, the label should get the value "Xamarin Forms Header" initialized in the MainPageModel.
I have the fully runnable source on github here, but here's the code. Can someone see what the issue is?
MainPage.xaml
<local:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
x:Class="SampleApp.MainPage">
<StackLayout>
</StackLayout>
</local:PageBase>
MainPageModel.xaml
public class MainPageModel : FreshBasePageModel
{
public MainPageModel()
{
LabelText = "Xamarin Forms Header";
}
public string LabelText { get; set; }
}
PageBase.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SampleApp.PageBase">
<ContentPage.ControlTemplate>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding LabelText}" />
<ContentPresenter Grid.Row="1" />
</Grid>
</ControlTemplate>
</ContentPage.ControlTemplate>
</ContentPage>
you could try to change like this:
MainPage.xaml :
<?xml version="1.0" encoding="utf-8" ?>
<local:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
x:Class="SampleApp.MainPage"
LabelText ="{Binding LabelText} "
>
<StackLayout>
</StackLayout>
</local:PageBase>
PageBase.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="SampleApp.PageBase">
<ContentPage.ControlTemplate>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{TemplateBinding LabelText}" />
<ContentPresenter Grid.Row="1" />
</Grid>
</ControlTemplate>
</ContentPage.ControlTemplate>
</ContentPage>
in your PageBase.xaml.cs:
public partial class PageBase : ContentPage
{
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create("LabelText", typeof(string), typeof(PageBase), "Control Template Demo App");
public string LabelText
{
get { return (string)GetValue(LabelTextProperty); }
}
public PageBase ()
{
InitializeComponent ();
}
}
you could refer to TemplateBinding
TemplateBinding doesn't bind to the View Model so whole code is fundamentally wrong, please read about the topic https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/control-templates/template-binding
Also of note, this would likely work if you used Binding instead of TemplateBinding, but I don't think it makes sense to do that as said something is fundamentally wrong.

Hamburger Menu Xamarin Forms (MasterDetailPage)

I'm new enough to use Xamarin, in my Xamarin Forms project I created a Master-Detail Page and in the ListView that represents the menu I wanted to put Title and Icon, for icon images I have to insert each icon in all device projects?
And I also have a small problem, when I click on a menu item and navigate to the selected Detail page, the hamburger menu disappears
MainPageMaster.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="XXX"
Title="Master">
<StackLayout>
<ListView x:Name="MenuItemsListView"
SeparatorVisibility="None"
HasUnevenRows="true"
ItemsSource="{Binding MenuItems}">
<ListView.Header>
<Grid BackgroundColor="#03A9F4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="6"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Label
Grid.Column="1"
Grid.Row="1"
Text="B1 Term"
HorizontalTextAlignment="Center"
Style="{DynamicResource SubtitleStyle}"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout VerticalOptions="FillAndExpand"
Orientation="Horizontal"
Padding="20,10,0,10"
Spacing="20">
<Image Source="{Binding Icon}"
WidthRequest="40"
HeightRequest="40"
VerticalOptions="Center" />
<Label Text="{Binding Title}"
FontSize="Medium"
VerticalOptions="Center"
TextColor="Black"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
File .cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPageMaster : ContentPage
{
public ListView ListView;
public MainPageMaster()
{
InitializeComponent();
BindingContext = new MainPageMasterViewModel();
ListView = MenuItemsListView;
}
class MainPageMasterViewModel : INotifyPropertyChanged
{
public ObservableCollection<MainPageMenuItem> MenuItems { get; set; }
public MainPageMasterViewModel()
{
MenuItems = new ObservableCollection<MainPageMenuItem>(new[]
{
new MainPageMenuItem { Id = 0, Icon="ic_menu_home.png",Title = "Home", TargetType = typeof(MainPageDetail) },
new MainPageMenuItem { Id = 1, Title = "Elenco Clienti", TargetType = typeof(ElencoClientiPage) },
new MainPageMenuItem { Id = 2, Title = "Logout", TargetType = typeof(LogOut) }
});
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged == null)
return;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
Screen
In this image, my icon isn't visible but I add an image in Android project
Creating the master-detail page:
Add a content page and change the code as follows :
RootPage.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:local="clr-namespace: your_NameSpace"
x:Class="your_NameSpace.RootPage">
</MasterDetailPage>
RootPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RootPage : MasterDetailPage
{
public RootPage()
{
InitializeComponent();
}
}
Creating its Menu Page:
Add another content page and change the code as follows :
MenuPage.xaml (Design of the actual hamburger menu)
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage BackgroundColor="White"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="your_NameSpace.MenuPage">
<ContentPage.Padding >
<OnPlatform x:TypeArguments="Thickness" iOS=" 0 , 20 , 0 , 0" />
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout BackgroundColor="White" Padding ="10 , 30 , 10, 10">
<Button Text="Login" BackgroundColor="White" TextColor="DarkGray" HorizontalOptions="StartAndExpand" Command="{Binding GoHomeCommand}" />
<BoxView HeightRequest="0.5" HorizontalOptions="FillAndExpand" BackgroundColor="Gray"/>
<Button Text="Search" BackgroundColor="White" TextColor="DarkGray" HorizontalOptions="StartAndExpand" Command="{Binding GoSecondCommand}" />
<BoxView HeightRequest="0.5" HorizontalOptions="FillAndExpand" BackgroundColor="Gray"/>
<Button Text="Browse" TextColor="DarkGray" BackgroundColor="White" HorizontalOptions="StartAndExpand" Command="{Binding GoThirdCommand}"/>
<BoxView HeightRequest="0.5" HorizontalOptions="FillAndExpand" BackgroundColor="Gray"/>
</StackLayout>
</ContentPage.Content>
MenuPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuPage : ContentPage
{
public MenuPage()
{
BindingContext = new MenuPageViewModel();
this.Icon = "yourHamburgerIcon.png"; //only neeeded for ios
InitializeComponent();
}
}
Its model class :
This is where the button click commands of the menu page are bound in
MenuPageViewModel.cs
public class MenuPageViewModel
{
public ICommand GoHomeCommand { get; set; }
public ICommand GoSecondCommand { get; set; }
public ICommand GoThirdCommand { get; set; }
public MenuPageViewModel()
{
GoHomeCommand = new Command(GoHome);
GoSecondCommand = new Command(GoSecond);
GoThirdCommand = new Command(GoThird);
}
void GoHome(object obj)
{
App.NavigationPage.Navigation.PopToRootAsync();
App.MenuIsPresented = false;
}
void GoSecond(object obj)
{
App.NavigationPage.Navigation.PushAsync(new Home()); //the content page you wanna load on this click event
App.MenuIsPresented = false;
}
void GoThird(object obj)
{
App.NavigationPage.Navigation.PushAsync(new ClinicInformation());
App.MenuIsPresented = false;
}
}
Add the following properties in your application class usually, the name for your application class is App.xaml and App.xaml.cs
Add the following to your App.xaml.cs:
public static NavigationPage NavigationPage { get; private set; }
public static RootPage RootPage;
public static bool MenuIsPresented
{
get
{
return RootPage.IsPresented;
}
set
{
RootPage.IsPresented = value;
}
}
Here RootPage is a static instance of your master-detail page,
NavigationPage is your detail page that you change to change your detail page,
IsMenuPresentend is the bool than when true keeps the MenuPage open and when false closes the same.
After doing all this add this function in your application class and call it in its constructor of your App.Xaml.cs
private void CallMain()
{
var menuPage = new MenuPage();
NavigationPage = new NavigationPage(new Home());
RootPage = new RootPage();
RootPage.Master = menuPage;
RootPage.Detail = NavigationPage;
MainPage = RootPage;
}
In your Android project add the following theme:
values/styles.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MyTheme" parent="MyTheme.Base">
</style>
<style name="DrawerArrowStyle"
parent="#style/Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">#FFFFFF</item>
</style>
<style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">#003399</item>
<item name="colorPrimaryDark">#003399</item>
<item name="colorControlHighlight">#003399</item>
<item name="colorAccent">#012348</item>
<item name="drawerArrowStyle">#style/DrawerArrowStyle</item>
</style>
</resources>
Create a folder named values-v21 and add an XML named styles.xml and add the following code to it :
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MyTheme" parent="MyTheme.Base">
<item name="android:windowContentTransitions">true</item>
<item name="android:windowAllowEnterTransitionOverlap">true</item>
<item name="android:textAllCaps">false</item>
<item name="android:windowAllowReturnTransitionOverlap">true</item>
<item name="android:windowSharedElementEnterTransition">#android:transition/move</item>
<item name="android:windowSharedElementExitTransition">#android:transition/move</item>
</style>
</resources>
And use the name myTheme as the app theme in all your Android activities.
There you go your hamburger menu is complete in case you have any queries feel free to comment.
Good luck!
Happy Coding.
You can try this as well for detailed information
Hamburger Menu tutorial
To show Humberger menu icon in Android and iOS application you can use Title = "☰" a special character. This going to show menu icon properly.
<MasterDetailPage.Master>
<ContentPage Title = "☰" BackgroundColor="Red">
<StackLayout BackgroundColor = "#B2EC5D" >
< ListView x:Name="navigationDrawerList">
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>

Resources