Reputation: 43
I am developing a mobile app with .Net MAUI without using shell and came up with a question.
When using shell to navigate pages, AppShell.xaml
would look like this:
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
and you would be able to move aournd pages.
When you don't use shell, App.xaml.cs
would look like this:
public App(){
MainPage = new MainPage();
//or
MainPage = new NavigationPage(new MainPage());
}
Then, if you have MainPageViewModel.cs
to enable data binding, the constructor in MainPage.xaml.cs
would need to take this in the parameter in order to set it to BindingContext
.
public partial class MainPage : Flyout
{
public MainPage(MainPageViewModel viewModel){
InitializeComponent();
BindingContext = viewModel;
}
}
Here, I can think of two cases where
1. you pass the parameter when you call the page in App.xaml.cs
:
public App(){
MainPage = new MainPage(new ViewModels.MainPageViewModel());
//If MainPageViewModel() needs a parameter, it would be longer and longer depending on the structure
MainPage = new MainPage(new ViewModels.MainPageViewModel(new DatabaseContext()));
}
2. you don't pass anything, make a constructor with no parameter in MainPage.xaml.cs
, instantiate MainPageViewModel
there:
App.xaml.cs
:
public App(){
MainPage = new MainPage();
}
MainPage.xaml.cs
:
public MainPage(){
InitializeComponent();
BindingContext = new MainPageViewModel();
}
I was wondering how those two differ essentially and what are downsides of doing those.
I watched tutorial videos of building .Net MAUI apps, but most of them used shell to navigate pages and didn't have a lot of resources for this case.
Upvotes: 0
Views: 2299
Reputation: 3251
Typically, I don't like to register and inject or pass ViewModels into pages and instead use DI to pull the services needed by the ViewModel and let the page create a new ViewModel each time, which is set in XAML.
<ContentPage.BindingContext>
<vm:MainViewModel/>
</ContentPage.BindingContext>
This way XAML will give you autocomplete based on the ViewModel properties and you don't have to worry about the Page being a potential memory leak as much. For example, when there's a single registered instance of the ViewModel the page may get held onto because it never cleared the BindingContext after being popped, which still has a reference to that registered instance of the ViewModel.
I use a helper class to pull any services the ViewModel would need.
public static class ServiceHelper
{
public static IServiceProvider Services { get; private set; }
public static void Initialize(IServiceProvider serviceProvider) =>
Services = serviceProvider;
public static T GetService<T>() => Services.GetService<T>();
}
Then in the ViewModel use it to get the service
private readonly INavigationService _navigationService = ServiceHelper.GetService<INavigationService>()
Just don't forget to register everything in your MauiProgram.cs
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.Services.AddSingleton<INavigationService, NavigationService>()
var app = builder.Build();
ServiceHelper.Initialize(app.Services);
return app;
Upvotes: 2