I inherited a Xamarin project that has to be migrated to .Net MAUI. My current issue is that the hamburger icon is not visible. I can drag the menu from the left hand side, and works fine.
It’s built with a flyout page and a navigation service that to be honest, this last one I don’t trully understand.
If I comment the initialization of the service, the hamburger icon appeares but the menu items throw an exception once clicked.
I already took a look at github but it’s seems to be a current issue: https://github.com/dotnet/maui/issues/22116 https://github.com/dotnet/maui/issues/18228
The main goal is to have a hamburger menu item that displays the flyoutpage to enable the user navigate all the pages. But due to the project built arround this navigation service, the routing, viewmodels initialization, and so on. I fear that if I bypass it I would have to do a lot of recode.
Does anyone faced the same problem and have a workarround?
public partial class App : Application
{
public App()
{
InitializeComponent();
Resources["DefaultStringResources"] = new Resx.AppResources();
DependencyService.Register<SoapServices>();
DependencyService.Register<SQLiteHelper>();
DependencyService.Register<BackgroundServiceImplementation>();
DependencyService.Register<PdfService>();
InitApp();
InitLoggerService();
VersionTracking.Track();
MainPage = new RootMasterDetailView();
//DependencyService.Get<ISQLiteHelper>().ImportDatabase("KoreDatabase.db3");
}
//protected override Window CreateWindow(IActivationState activationState)
//{
// MainPage = new RootMasterDetailView();
// return base.CreateWindow(activationState);
//}
private void InitLoggerService()
{
var loggerService = ViewModelLocator.Resolve<ILoggerService>();
loggerService.InitializeAnalytics();
}
private void InitApp()
{
VersionTracking.Track();
Settings.UrlBase = Constants.BaseUrl;
ViewModelLocator.RegisterDependencies();
}
protected override async void OnStart()
{
base.OnStart();
//await InitNavigation(); // ********* WHEN COMMENTED, THE HAMBURGER ICON APPEARES
}
private Task InitNavigation()
{
var navigationService = ViewModelLocator.Resolve<INavigationService>();
return navigationService.InitializeAsync();
}
}
public Task InitializeAsync()
{
if (!Settings.IsLoggedIn)
{
return NavigateToAsync<LoginViewModel>();
}
else
{
if (Settings.FinishedFirstSync)
{
return NavigateToAsync<RootMasterDetailViewModel>();
}
else
{
return NavigateToAsync<StatusViewModel>(true);
}
}
}
public Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase
{
return InternalNavigateToAsync(typeof(TViewModel), null);
}
public Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase
{
return InternalNavigateToAsync(typeof(TViewModel), parameter);
}
private async Task InternalNavigateToAsync(Type viewModelType, object parameter)
{
//_loggerService.RegisterNavigationEvent(viewModelType, parameter);
Page page = CreatePage(viewModelType, parameter);
// if (page is LoginView)
// {
// Application.Current.MainPage = new CustomNavigationView(page);
// }
// else
// {
var navigationPage = Application.Current.MainPage as NavigationPage;
if (navigationPage != null)
{
await navigationPage.PushAsync(page);
}
else
{
Application.Current.MainPage = new NavigationPage(page);
}
// }
await InitializePage(page, parameter);
}
private async Task InitializePage(Page page, object parameter = null)
{
if ((page.BindingContext as ViewModelBase).Initialized)
return;
await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
if (page is FlyoutPage)
{
await InitializePage(((FlyoutPage)page).Flyout, null);
await InitializePage(((FlyoutPage)page).Detail, null);
}
else if (page is TabbedPage)
{
foreach (var child in (page as TabbedPage).Children)
{
await InitializePage(child, parameter);
}
}
else if (page is NavigationPage)
{
await InitializePage((page as NavigationPage).CurrentPage, null);
}
}
Agus is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
While this might be considered a workaround, it “should” be broadly compatible since you mentioned a valid concern about having to do a lot of recoding. What I tend to do a lot is hide the default navigation bar and do something like this instead.
In other words, I make “a” hamburger menu rather than try to deal with “the” hamburger menu which can vary by platform. As an example, here’s the xaml for my custom search bar, and you might be able to adapt it for your purposes. When clicked, it’s just going to make a call on the shell, which is already “wired” to work.
private void OnToggleFlyout(object o, EventArgs e)
{
var shell = (AppShell)Shell.Current;
shell.FlyoutIsPresented = !shell.FlyoutIsPresented;
}
Example xaml for custom search navigation bar
<ContentView
x:Name="viewNavigationBarWithSearch"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:IVSoftware.Maui.Quatch.OnePage.Views"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="IVSoftware.Maui.Quatch.OnePage.Components.NavigationBarWithSearch">
<Grid
BackgroundColor="White"
RowDefinitions="1,*,2"
HeightRequest="{Binding NavBarHeight}">
<BoxView
Grid.Row="0"
Grid.ColumnSpan="2"
BackgroundColor="DarkSlateGray"
Margin="0"/>
<Grid
Grid.Row="1"
ColumnDefinitions="*,Auto">
<!-- Binding is View e.g. Containers, Items...-->
<SearchBar
x:Name="searchBar"
Grid.Column="0"
Placeholder="Search..."
Text="{Binding SearchText}"
SearchCommand="{Binding SearchCommand}"
SearchCommandParameter="{Binding Text, Source={x:Reference searchBar}}"
CancelButtonColor="Transparent"/>
<Button
x:Name="buttonClearList"
Grid.Column="0"
HorizontalOptions="End"
VerticalOptions="Center"
Text="X"
FontSize="16"
FontAttributes="Bold"
TextColor ="#222222"
BorderWidth="-1"
WidthRequest="40"
Padding="0"
Margin="0,0,10,0"
IsVisible="false"/>
<Button
x:Name="menuButton"
Text="☰"
Grid.Column="1"
VerticalOptions="Center"
BorderWidth="-1"
Padding="4"
Margin="4"
TextColor="Black"
FontAttributes="Bold"
FontSize="16"
Clicked="OnToggleFlyout"
BackgroundColor="Transparent"
IsVisible="{OnPlatform WinUI='False', Default='True'}"/>
</Grid>
<BoxView
Grid.Row="2"
Grid.ColumnSpan="2"
BackgroundColor="DarkSlateGray"
Margin="0"/>
</Grid>
</ContentView>