maui

GitHub

提供.NET MAUI跨平台应用开发指导,涵盖Android/iOS/macOS/Windows构建、MVVM模式、设备集成及Xamarin迁移。

catalog/Frameworks/MAUI/skills/maui/SKILL.md managedcode/dotnet-skills

Trigger Scenarios

进行跨平台移动或桌面UI开发 集成设备能力或导航逻辑 迁移Xamarin.Forms项目

Install

npx skills add managedcode/dotnet-skills --skill maui -g -y
More Options

Non-standard path

npx skills add https://github.com/managedcode/dotnet-skills/tree/main/catalog/Frameworks/MAUI/skills/maui -g -y

Use without installing

npx skills use managedcode/dotnet-skills@maui

指定 Agent (Claude Code)

npx skills add managedcode/dotnet-skills --skill maui -a claude-code -g -y

安装 repo 全部 skill

npx skills add managedcode/dotnet-skills --all -g -y

预览 repo 内 skill

npx skills add managedcode/dotnet-skills --list

SKILL.md

Frontmatter
{
    "name": "maui",
    "description": "Build, review, or migrate .NET MAUI applications across Android, iOS, macOS, and Windows with correct cross-platform UI, platform integration, and native packaging assumptions. USE FOR: working on cross-platform mobile or desktop UI in .NET MAUI; integrating device capabilities, navigation, or platform-specific code; migrating Xamarin.Forms or aligning. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.",
    "compatibility": "Requires .NET MAUI workload (.NET 8+)."
}

.NET MAUI

Trigger On

  • working on cross-platform mobile or desktop UI in .NET MAUI
  • integrating device capabilities, navigation, or platform-specific code
  • migrating Xamarin.Forms or aligning a shared codebase across targets
  • implementing MVVM patterns in mobile apps

Documentation

References

  • patterns.md - Shell navigation, platform-specific code, messaging, lifecycle, data binding, and CollectionView patterns
  • anti-patterns.md - Common MAUI mistakes and how to avoid them

Platform Targets

Platform Build Host Notes
Android Windows/Mac Emulator or device
iOS Mac only Requires Xcode
macOS Mac only Catalyst
Windows Windows WinUI 3

Workflow

  1. Confirm target platforms — behavior differs across Android, iOS, Mac, Windows
  2. Separate shared UI and platform code — use handlers and DI
  3. Follow MVVM pattern — keep views dumb, logic in ViewModels
  4. Handle lifecycle and permissions — platform contracts need testing
  5. Test on real devices — emulators don't catch everything

Current Upstream Notes

  • .NET MAUI 10.0.90 is a broad quality release for the 10.0 line. It fixes grouped CollectionView scrolling, layout, selection, and retention paths; Android BlazorWebView back handling; WebView rendering and lifecycle leaks; Shell/navigation regressions; and several shared-resource, handler, map, SafeArea, and accessibility issues.
  • After upgrading MAUI packages, smoke-test grouped and virtualized CollectionView flows, Shell/modal/back navigation, tabs, keyboard and SafeArea interactions, maps, WebView/HybridWebView lifecycle, memory retention, and accessibility narration on every shipped target.
  • The August 2026 .NET MAUI Learn overview for net-maui-10.0 still frames the platform around a shared single-project app, native API access, handlers, and optional Blazor Hybrid UI. Verify each target platform rather than treating shared code as identical runtime behavior.

Project Structure

MyApp/
├── MyApp/                    # Shared code
│   ├── App.xaml              # Application entry
│   ├── MauiProgram.cs        # DI and configuration
│   ├── Views/                # XAML pages
│   ├── ViewModels/           # MVVM ViewModels
│   ├── Models/               # Domain models
│   ├── Services/             # Business logic
│   └── Platforms/            # Platform-specific code
│       ├── Android/
│       ├── iOS/
│       ├── MacCatalyst/
│       └── Windows/
└── MyApp.Tests/

MVVM Pattern

ViewModel with MVVM Toolkit

public partial class ProductsViewModel(IProductService productService) : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<Product> _products = [];

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(LoadProductsCommand))]
    private bool _isLoading;

    [RelayCommand(CanExecute = nameof(CanLoadProducts))]
    private async Task LoadProductsAsync()
    {
        IsLoading = true;
        try
        {
            var items = await productService.GetAllAsync();
            Products = new ObservableCollection<Product>(items);
        }
        finally
        {
            IsLoading = false;
        }
    }

    private bool CanLoadProducts() => !IsLoading;
}

View Binding

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MyApp.ViewModels"
             x:Class="MyApp.Views.ProductsPage"
             x:DataType="vm:ProductsViewModel">

    <RefreshView Command="{Binding LoadProductsCommand}"
                 IsRefreshing="{Binding IsLoading}">
        <CollectionView ItemsSource="{Binding Products}">
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="models:Product">
                    <VerticalStackLayout Padding="10">
                        <Label Text="{Binding Name}" FontSize="18" />
                        <Label Text="{Binding Price, StringFormat='{0:C}'}" />
                    </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </RefreshView>
</ContentPage>

Dependency Injection

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });

        // Services
        builder.Services.AddSingleton<IProductService, ProductService>();
        builder.Services.AddSingleton<INavigationService, NavigationService>();

        // ViewModels
        builder.Services.AddTransient<ProductsViewModel>();
        builder.Services.AddTransient<ProductDetailViewModel>();

        // Pages
        builder.Services.AddTransient<ProductsPage>();
        builder.Services.AddTransient<ProductDetailPage>();

        return builder.Build();
    }
}

Navigation

Shell Navigation

// Register routes
Routing.RegisterRoute(nameof(ProductDetailPage), typeof(ProductDetailPage));

// Navigate with parameters
await Shell.Current.GoToAsync($"{nameof(ProductDetailPage)}?id={product.Id}");

// Receive parameters
[QueryProperty(nameof(ProductId), "id")]
public partial class ProductDetailViewModel : ObservableObject
{
    [ObservableProperty]
    private string _productId;

    partial void OnProductIdChanged(string value)
    {
        LoadProduct(value);
    }
}

Navigation Service

public interface INavigationService
{
    Task NavigateToAsync<TViewModel>(object? parameter = null);
    Task GoBackAsync();
}

public class NavigationService : INavigationService
{
    public async Task NavigateToAsync<TViewModel>(object? parameter = null)
    {
        var route = typeof(TViewModel).Name.Replace("ViewModel", "Page");
        var query = parameter is null ? "" : $"?id={parameter}";
        await Shell.Current.GoToAsync($"{route}{query}");
    }

    public Task GoBackAsync() => Shell.Current.GoToAsync("..");
}

Platform-Specific Code

Using Partial Classes

// Services/DeviceService.cs (shared)
public partial class DeviceService
{
    public partial string GetDeviceId();
}

// Platforms/Android/DeviceService.cs
public partial class DeviceService
{
    public partial string GetDeviceId()
    {
        return Android.Provider.Settings.Secure.GetString(
            Android.App.Application.Context.ContentResolver,
            Android.Provider.Settings.Secure.AndroidId);
    }
}

// Platforms/iOS/DeviceService.cs
public partial class DeviceService
{
    public partial string GetDeviceId()
    {
        return UIKit.UIDevice.CurrentDevice.IdentifierForVendor?.ToString() ?? "";
    }
}

Conditional Compilation

public string GetPlatformInfo()
{
#if ANDROID
    return $"Android {Android.OS.Build.VERSION.Release}";
#elif IOS
    return $"iOS {UIKit.UIDevice.CurrentDevice.SystemVersion}";
#elif MACCATALYST
    return "macOS Catalyst";
#elif WINDOWS
    return "Windows";
#else
    return "Unknown";
#endif
}

Anti-Patterns to Avoid

Anti-Pattern Why It's Bad Better Approach
God ViewModel Unmaintainable Split into focused ViewModels
Logic in code-behind Hard to test Use MVVM and commands
Platform code everywhere Defeats cross-platform Use handlers/DI
Direct service calls in Views Tight coupling Use ViewModel
Ignoring lifecycle Crashes, leaks Handle lifecycle events

Performance Best Practices

  1. Use compiled bindings:

    <ContentPage x:DataType="vm:ProductsViewModel">
    
  2. Virtualize long lists:

    <CollectionView ItemsSource="{Binding Items}"
                    ItemSizingStrategy="MeasureFirstItem" />
    
  3. Optimize images:

    var image = ImageSource.FromFile("image.png");
    // Use appropriate resolution for platform
    
  4. Avoid synchronous work on UI thread:

    // Bad
    var data = service.GetData(); // Blocks UI
    
    // Good
    var data = await service.GetDataAsync();
    

Testing

[Fact]
public async Task LoadProducts_UpdatesCollection()
{
    var mockService = new Mock<IProductService>();
    mockService.Setup(s => s.GetAllAsync())
        .ReturnsAsync(new[] { new Product { Name = "Test" } });

    var viewModel = new ProductsViewModel(mockService.Object);

    await viewModel.LoadProductsCommand.ExecuteAsync(null);

    Assert.Single(viewModel.Products);
    Assert.Equal("Test", viewModel.Products[0].Name);
}

Deliver

  • shared MAUI code with explicit platform seams
  • MVVM pattern with testable ViewModels
  • navigation and lifecycle behavior that fits each target
  • a realistic build and deployment path for the chosen platforms

Validate

  • cross-platform reuse is real, not superficial
  • platform-specific behavior is isolated and testable
  • MVVM pattern is followed consistently
  • build assumptions for Mac/iOS and Windows are explicit
  • performance is acceptable on target devices

Version History

  • 0559476 Current 2026-08-19 23:31
  • 7ab7f03 2026-07-25 05:22

Same Skill Collection

catalog/Frameworks/gRPC/skills/grpc/SKILL.md
catalog/Frameworks/Official-Astro/skills/astro-developer/SKILL.md
catalog/Frameworks/Official-DotNet-ASPNetCore/skills/configuring-opentelemetry-dotnet/SKILL.md
catalog/Frameworks/Official-DotNet-ASPNetCore/skills/dotnet-webapi/SKILL.md
catalog/Frameworks/Official-DotNet-ASPNetCore/skills/minimal-api-file-upload/SKILL.md
catalog/Frameworks/Orleans/skills/orleans/SKILL.md
catalog/Frameworks/ThreeJS-WebGPU-TSL/skills/webgpu-threejs-tsl/SKILL.md
catalog/Libraries/Official-DotNet-Data/skills/optimizing-ef-core-queries/SKILL.md
catalog/Platform/Official-DotNet-Advanced/skills/csharp-scripts/SKILL.md
catalog/Platform/Official-DotNet-Advanced/skills/nuget-trusted-publishing/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/create-blazor-project/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/fetch-and-send-data/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/support-prerendering/SKILL.md
catalog/Platform/Official-DotNet-Blazor/skills/use-js-interop/SKILL.md
catalog/Platform/Official-DotNet-Experimental/skills/exp-mock-usage-analysis/SKILL.md
catalog/Platform/Official-DotNet-Experimental/skills/exp-simd-vectorization/SKILL.md
catalog/Platform/Official-DotNet-Test-Migration/skills/migrate-xunit-to-mstest/SKILL.md
catalog/Platform/Official-DotNet-Test-Migration/skills/migrate-xunit-to-xunit-v3/SKILL.md
catalog/Platform/Official-DotNet-Upgrade/skills/dotnet-aot-compat/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/code-testing-extensions/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/filter-syntax/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/find-untested-sources/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/platform-detection/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/scaffold-dotnet-test-project/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/test-gap-analysis/SKILL.md
catalog/Testing/Official-DotNet-Test/skills/testability-obstacle/SKILL.md
catalog/Testing/Playwright/skills/playwright-visual-testing/SKILL.md
catalog/Testing/xUnit/skills/xunit/SKILL.md
catalog/Tools/Code-Analysis/skills/code-analysis/SKILL.md
catalog/Tools/HTMLHint/skills/htmlhint/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/analyzing-dotnet-performance/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/clr-activation-debugging/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/dotnet-trace-collect/SKILL.md
catalog/Tools/Official-DotNet-Diagnostics/skills/dump-collect/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/binlog-failure-analysis/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/copy-to-output-directory/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/msbuild-server/SKILL.md
catalog/Tools/Official-DotNet-MSBuild/skills/resolve-project-references/SKILL.md
catalog/Tools/ReportGenerator/skills/reportgenerator/SKILL.md
catalog/Tools/ReSharper-CLT/skills/resharper-clt/SKILL.md
catalog/Tools/Roslynator/skills/roslynator/SKILL.md
catalog/Tools/Stylelint/skills/stylelint/SKILL.md
external-sources/upstreams/webgpu-claude-skill/skills/webgpu-threejs-tsl/SKILL.md
catalog/Frameworks/ASP.NET-Core/skills/aspnet-core/SKILL.md
catalog/Frameworks/Aspire/skills/aspire/SKILL.md
catalog/Frameworks/Azure-Functions/skills/azure-functions/SKILL.md
catalog/Frameworks/Blazor/skills/blazor/SKILL.md
catalog/Frameworks/Entity-Framework-6/skills/entity-framework6/SKILL.md
catalog/Frameworks/Entity-Framework-Core/skills/entity-framework-core/SKILL.md

Metadata

Files
0
Version
0559476
Hash
8f4e4f59
Indexed
2026-07-25 05:22

inicio - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-21 07:40
浙ICP备14020137号-1 $mapa de visitantes$