Spoiler
Si avrà un progetto multipiattaforma con pattern MVVM e navigazione, perfettamente funzionante.
Prerequisiti
Per iniziare non serve molto, basta il Framework .net (al momento della scrittura viene utilizzata la versione 8.0) e Visual Studio Community
Iniziamo
Dopo essere entrati nella cartella del progetto (eventualmente clonando il repository vuoto da GitHub) facciamo in modo di creare una nuova Solution .net e i suoi singoli progetti (Project) da riga di comando:
dotnet new sln -n "PizzaLab.Frontend"
dotnet new maui -n "PizzaLab.MAUI"
dotnet new mauilib -n "PizzaLab.MAUI.ViewModels"
dotnet new mauilib -n "PizzaLab.MAUI.Views"
Andiamo ora a legare (e quindi includere) questi Project nella Solution:
dotnet sln PizzaLab.Frontend.sln add .\PizzaLab.MAUI\PizzaLab.MAUI.csproj
dotnet sln PizzaLab.Frontend.sln add .\PizzaLab.MAUI.ViewModels\PizzaLab.MAUI.ViewModels.csproj
dotnet sln PizzaLab.Frontend.sln add .\PizzaLab.MAUI.Views\PizzaLab.MAUI.Views.csproj
Come si può vedere viene creata una Solution e tre diversi Project, uno di tipo MAUI App
e due di tipo MAUI Class Library
. Il Project MAUI si prenderà carico di far funzionare il tutto, anche su sistemi operativi diversi (Windows, MacOS, Android e iOS); il Project .ViewModels conterrà al suo interno tutti i ViewModel e, ovviamente, il Project .Views avrà al suo interno tutte le View.
Ora apriamo la Solution:

In PizzaLab.MAUI cancelliamo AppShell.xaml
e MainPage.xaml
. Se proviamo ora compilare avremo un errore dal momento che AppShell è stata cancellata. Entriamo quindi in App.xaml.cs
e cancelliamo la riga di codice che da errore. Ora tutto andrà a buon fine.
Dal momento che nel nostro progetto useremo Prism, andiamo ad aggiungere il riferimento a questa libreria tramite Nuget sia per PizzaLab.MAUI sia per PizzaLab.MAUI.ViewModels tramite Package Manager Console
:
install-package Prism.DryIoc.Maui
PizzaLab.MAUI.ViewModels
In .ViewModels cancelliamo Class1.cs
e al suo posto creiamo due classi (Class) la prima la chiamiamo ViewModelBase
e la seconda MainViewModel
.
ViewModelBase
sarà una classe astratta e il suo codice sarà questo:
public abstract class ViewModelBase : BindableBase, IDisposable
{
#region IDisposable
private bool _disposed = false;
~ViewModelBase()
=> Dispose(false);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
}
_disposed = true;
}
}
#endregion
private readonly INavigationService _navigationService;
protected INavigationService NavigationService
=> _navigationService;
protected ViewModelBase(
INavigationService navigationService
)
{
_navigationService = navigationService;
}
}
MainViewModel
invece sarà il nostro primo vero ViewModel e avrà come contenuto questo:
public partial class MainViewModel : ViewModelBase
{
#region IDisposable
private bool _disposed = false;
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
}
_disposed = true;
}
base.Dispose(disposing);
}
#endregion
public MainViewModel(
INavigationService navigationService
)
: base(navigationService)
{
}
}
PizzaLab.MAUI.Views
Passiamo ora al progetto .Views nel quale cancelliamo Class1.cs
e al suo posto creiamo una .NET MAUI ContentPage (XAML)
che chiameremo MainView
. Niente altro da fare qui.
Se si prova a ricompllare tutto andà a buon fine.
PizzaLab.MAUI
Aggiungiamo ora i riferimenti (References) dei nostri progetti .ViewModels e .Views al nostro progetto .MAUI nelle sue dipendenze (Dependencies) e una volta fatto modifichiamo il codice della classe statica MauiProgram
in questo modo:
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
.UsePrism(prism =>
prism.ConfigureServices(services =>
{
services.AddScoped<MainViewModel>();
})
.ConfigureLogging(builder =>
{
builder.AddDebug();
})
.RegisterTypes(containerRegistry =>
{
containerRegistry.RegisterForNavigation<MainView, MainViewModel>("MainView");
})
.CreateWindow(async navigationService =>
{
await navigationService.NavigateAsync("/" + nameof(NavigationPage) + "/" + "MainView");
})
);
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
Aggiungere quindi il riferimento ai due progetti all’interno della classe:
using PizzaLab.MAUI.ViewModels;
using PizzaLab.MAUI.Views;
Ritocco finale e deploy
Aggiorniamo tutti i pacchetti Nuget
dal Package Manager Console
:
update-package
Abilitiamo il Deploy per il pogetto .MAUI da Configuration Manager
della soluzione e proviamo ad avviare.

Risultato su Windows:

E quello sull’emulatore Android:

Qui trovate i sorgenti del codice visto sopra: