Voici comment créer un menu hamburger dans un projet Xamarin Forms en quelques étapes.
(Source : developer.xamarin.com)
Dans un premier temps, nous allons créer un ViewModel.
// MenuItem.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Project.Views;
namespace Project.ViewsModels
{
public class MenuItem
{
public MenuItem()
{
TargetType = typeof(HomePage);
}
public int Id { get; set; }
public string Title { get; set; }
public string ImageName { get; set; }
public Type TargetType { get; set; }
}
}
Il faut ensuite créer un autre ViewModel qui créera tous les MenuItems que l'on souhaite afficher.
// MenuPageViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Project.Views;
using Project.ViewsModels;
namespace Project.ViewModels
{
class MenuPageViewModel : INotifyPropertyChanged
{
public ObservableCollection MenuItems { get; set; }
public MenuPageViewModel()
{
MenuItems = new ObservableCollection(new[]
{
new MenuItem { Id = 0,
Title = Localization.AppResources.Menu_Home,
TargetType = typeof(HomePage),
ImageName = "home.png" },
new MenuItem { Id = 1,
Title = Localization.AppResources.Menu_Options,
TargetType = typeof(OptionsPage),
ImageName = "options.png" },
new MenuItem { Id = 2,
Title = Localization.AppResources.Menu_About,
TargetType = typeof(AboutPage),
ImageName = "about.png" },
});
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged == null)
return;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
A noter que HomePage, OptionsPage et AboutPage sont toutes les trois des ContentPage que j'ai créé au préalable.
Nous allons à présent créer une nouvelle ContentPage dans le dossier Views, qui affichera la liste des MenuItems.
<!-- MenuPage.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:i18n="clr-namespace:Project.Utils"
x:Class="Project.Views.MenuPage"
Title="{i18n:Translate Menu_Title}">
<StackLayout>
<ListView x:Name="MenuItemsListView"
SeparatorVisibility="None"
HasUnevenRows="true"
ItemsSource="{Binding MenuItems}">
<ListView.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="80"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Image Source="logo.png" HorizontalOptions="Center"
Grid.Column="1" Grid.Row="1"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="15,10" HorizontalOptions="FillAndExpand" Orientation="Horizontal">
<Image Source="{Binding ImageName}" WidthRequest="32"/>
<Label VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center"
Text="{Binding Title}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Dans le code behind nous allons rajouter une propriété ListView et initialiser le binding avec MenuPageViewModel.
// MenuPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Project.ViewModels;
using Project.Views.MenuViews;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MenuPage : ContentPage
{
public ListView ListView;
public MenuPage()
{
InitializeComponent();
BindingContext = new MenuPageViewModel();
ListView = MenuItemsListView;
}
}
}
La dernière étape, en ce qui concerne les vues, consiste à créer la MasterPageDetail.
<!-- 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:pages="clr-namespace:Project.Views"
x:Class="Project.Views.RootPage"
MasterBehavior="Popover">
<MasterDetailPage.Master>
<pages:MenuPage x:Name="MasterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<pages:HomePage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
// RootPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Project.ViewsModels;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RootPage : MasterDetailPage
{
public RootPage()
{
InitializeComponent();
MasterPage.ListView.ItemSelected += ListView_ItemSelected;
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as ViewsModels.MenuItem;
if (item == null)
return;
var page = (Page)Activator.CreateInstance(item.TargetType);
page.Title = item.Title;
if (item.Id == 0)
{
// Reinit the navigation stack
Detail = new NavigationPage(page);
}
else
{
// Push the new page to the navigation stack
((NavigationPage)Detail).Navigation.PushAsync(page);
}
IsPresented = false;
MasterPage.ListView.SelectedItem = null;
}
}
}
Pour finir, il faut initialiser notre MasterPageDetail lors de l'initialisation de l'application.
// App.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Project.Services;
using Xamarin.Forms;
namespace Project
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new Project.Views.RootPage();
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
Petit bonus, pour modifier la couleur de fond du menu.
<!-- App.xaml -->
<?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="Project.App">
<Application.Resources>
<!-- Application resource dictionary -->
<ResourceDictionary>
<!-- Colors -->
<Color x:Key="BackgroundColor">#2E2E2E</Color>
<!-- Styles -->
<Style TargetType="MasterDetailPage">
<Setter Property="BackgroundColor" Value="{StaticResource BackgroundColor}"/>
</Style>
<Style TargetType="ListView" x:Key="ListViewMenu">
<Setter Property="BackgroundColor" Value="{StaticResource BackgroundColor}"/>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Puis ajouter la propriété Style dans la balise ListView de MenuPage.xaml
:
Style="{StaticResource ListViewMenu}"
- Partager sur