📋 Daftar Isi
1. Pengenalan .NET MAUI
.NET MAUI (Multi-platform App UI) adalah framework dari Microsoft untuk membangun aplikasi cross-platform (Android, iOS, Windows, macOS) dari satu kode C# dan XAML. MAUI adalah penerus Xamarin.Forms dengan arsitektur yang lebih modern.
Arsitektur .NET MAUI
XAML + C#
Shared UI
& Business Logic
& Business Logic
→
.NET MAUI
Handler Mapping
Platform Abstraction
Platform Abstraction
→
Platforms
Android, iOS
Windows, macOS
Windows, macOS
Bash — Membuat Proyek MAUI
# Install MAUI workload dotnet workload install maui # Buat proyek baru dotnet new maui -n MyApp # Jalankan di Android dotnet build -t:Run -f net8.0-android # Jalankan di Windows dotnet build -t:Run -f net8.0-windows10.0.19041.0 # Jalankan di iOS dotnet build -t:Run -f net8.0-ios
2. XAML Layout
XAML — Halaman Utama
2.1 Layout Types
| Layout | Arah | Gunakan Untuk |
|---|---|---|
| VerticalStackLayout | Vertikal | Form, daftar item |
| HorizontalStackLayout | Horizontal | Toolbar, chip row |
| Grid | Baris & kolom | Dashboard, complex layout |
| FlexLayout | Wrap/nowrap | Tag cloud, responsive |
| AbsoluteLayout | Absolut | Overlay, floating element |
3. MVVM Pattern
C# — ViewModel
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private int _userCount;
[ObservableProperty]
private decimal _revenue;
[ObservableProperty]
private bool _isLoading;
private readonly IApiService _api;
public MainViewModel(IApiService api)
{
_api = api;
}
[RelayCommand]
private async Task RefreshAsync()
{
IsLoading = true;
try
{
var data = await _api.GetDashboardAsync();
UserCount = data.UserCount;
Revenue = data.Revenue;
}
catch (Exception ex)
{
await Shell.Current.DisplayAlert("Error", ex.Message, "OK");
}
finally
{
IsLoading = false;
}
}
[RelayCommand]
private async Task NavigateToDetailAsync(int userId)
{
await Shell.Current.GoToAsync($"detail?userId={userId}");
}
}
📋 CommunityToolkit.MVVM
Gunakan NuGet CommunityToolkit.Mvvm untuk source generators: [ObservableProperty] menghasilkan property + INotifyPropertyChanged, [RelayCommand] menghasilkan ICommand.
4. Shell Navigation
XAML — Shell Structure
C# — Shell Navigation Code
// Navigate with parameters
await Shell.Current.GoToAsync("detail", new Dictionary
{
["userId"] = 42,
["userName"] = "Budi"
});
// Receive parameters
[QueryProperty(nameof(UserId), "userId")]
[QueryProperty(nameof(UserName), "userName")]
public partial class DetailViewModel : ObservableObject
{
[ObservableProperty] private int _userId;
[ObservableProperty] private string _userName;
partial void OnUserIdChanged(int value)
{
// Load data when parameter arrives
LoadUserDetail(value);
}
}
5. Platform Specifics
C# — Platform-Specific Code
using Microsoft.Maui.Controls.PlatformConfiguration; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; // Platform-specific XAML// Platform check di C# #if ANDROID // Android-specific code var statusBar = Platform.CurrentActivity?.Window; statusBar?.SetStatusBarColor(Android.Graphics.Color.ParseColor("#2196F3")); #elif IOS // iOS-specific code UIApplication.SharedApplication.SetStatusBarStyle( UIStatusBarStyle.LightContent, false); #endif // Conditional compilation public static class PlatformHelper { public static bool IsAndroid => DeviceInfo.Platform == DevicePlatform.Android; public static bool IsIOS => DeviceInfo.Platform == DevicePlatform.iOS; public static bool IsDesktop => DeviceInfo.Idiom == DeviceIdiom.Desktop; } () .SetPrefersLargeTitles(true) /> () .SetBounce(true) />
6. Dependency Injection
C# — DI Configuration
// MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("FontAwesome.ttf", "FA");
});
// Services (Singleton - satu instance)
builder.Services.AddSingleton<IApiService, ApiService>();
builder.Services.AddSingleton<IDatabaseService, SqliteDatabase>();
// Services (Transient - baru setiap request)
builder.Services.AddTransient<IDialogService, DialogService>();
// ViewModels
builder.Services.AddTransient<MainViewModel>();
builder.Services.AddTransient<DetailViewModel>();
// Pages
builder.Services.AddTransient<MainPage>();
builder.Services.AddTransient<DetailPage>();
// HTTP Client
builder.Services.AddHttpClient("api", client =>
{
client.BaseAddress = new Uri("https://api.myapp.com");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
return builder.Build();
}
}
// Penggunaan di Page
public partial class MainPage : ContentPage
{
public MainPage(MainViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
}
}
7. Data Access
C# — SQLite Database
using SQLite;
public class LocalDatabase
{
private readonly SQLiteAsyncConnection _db;
public LocalDatabase(string dbPath)
{
_db = new SQLiteAsyncConnection(dbPath);
_db.CreateTableAsync<User>().Wait();
}
public Task<List<User>> GetUsersAsync() =>
_db.Table<User>().ToListAsync();
public Task<int> SaveUserAsync(User user) =>
user.Id != 0 ? _db.UpdateAsync(user) : _db.InsertAsync(user);
public Task<int> DeleteUserAsync(User user) =>
_db.DeleteAsync(user);
}
[Table("users")]
public class User
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(100)]
public string Name { get; set; } = string.Empty;
[MaxLength(200)]
public string Email { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; } = DateTime.Now;
}
8. Deployment
| Platform | Format | Distribusi |
|---|---|---|
| Android | AAB / APK | Google Play Store |
| iOS | IPA | App Store / TestFlight |
| Windows | MSIX / EXE | Microsoft Store / Sideload |
| macOS | DMG / PKG | Mac App Store / Direct |