mcpField
D
dotnet-uno-platform

dotnet-uno-platform

github.com/wshaddix開発8671 回インストール35 週間前に更新
リポジトリ

dotnet-uno-platform について

Uno Platform 5.x と .NET 8.0 以降のプロジェクト向け開発スキルで、アプリ構成、Extensions、MVUX、コントロール、テーマ、Hot Reload を扱います。Uno アプリの開発者を対象とし、ターゲット別のデプロイではなく共通のプロジェクト開発に重点を置きます。

主な機能

  1. 01単一プロジェクトのマルチターゲット構成
  2. 02ナビゲーションとサービス向け Extensions
  3. 03MVUX によるリアクティブなアプリ設計
  4. 04Toolkit のコントロールとヘルパー
  5. 05Material・Cupertino・Fluent テーマ
  6. 06XAML と C# の Hot Reload

活用シーン

  1. 01新しい Uno Platform アプリの構成
  2. 02リアクティブなデータフローとナビゲーションの追加
  3. 03Toolkit でアダプティブ UI を構築
  4. 04テーマ設定と UI のライブ反復

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-uno-platform

インストール後、Claude Code で/dotnet-uno-platformを入力して読み込まれたか確認します。

詳細

dotnet-uno-platform

Uno Platform のコア開発:Extensions エコシステム(ナビゲーション、DI、構成、シリアル化、ローカライズ、ロギング、HTTP、認証)、MVUX リアクティブパターン、Toolkit コントロール、テーマリソース(Material/Cupertino/Fluent)、ホットリロード、シングルプロジェクト構造を扱います。.NET 8.0+ をベースラインとする Uno Platform 5.x+ が対象です。

対象範囲の境界: このスキルは、Uno Platform のプロジェクト構造、Extensions エコシステムの構成、MVUX パターン、Toolkit コントロール、テーマ、ホットリロードを扱います。ターゲットごとのデプロイ(WASM、iOS、Android、Desktop、Embedded)は [skill:dotnet-uno-targets] が担当します。ライブドキュメント向けの MCP サーバー統合は [skill:dotnet-uno-mcp] が担当します。

対象外: Uno Platform のテスト(WASM 向け Playwright、プラットフォーム固有のテスト)については、[skill:dotnet-uno-testing] を参照してください。一般的なシリアル化パターンについては、[skill:dotnet-serialization] を参照してください。WASM 向け AOT/トリミングについては、[skill:dotnet-aot-wasm] を参照してください。UI フレームワーク選定の判断ツリーについては、[skill:dotnet-ui-chooser] を参照してください。

相互参照:[skill:dotnet-uno-targets] はターゲットごとのデプロイ、[skill:dotnet-uno-mcp] は MCP 統合、[skill:dotnet-uno-testing] はテストパターン、[skill:dotnet-serialization] はシリアル化の詳細、[skill:dotnet-aot-wasm] は WASM AOT、[skill:dotnet-ui-chooser] はフレームワーク選定、[skill:dotnet-accessibility] はアクセシビリティパターン(AutomationProperties、WASM での ARIA マッピング)を扱います。


シングルプロジェクト構造

Uno Platform 5.x は、マルチターゲット向けの条件付き TFM を使用するシングルプロジェクト構造を採用しています。1 つの .csproj でマルチターゲットによりすべてのプラットフォームを対象にします。


<Project Sdk="Uno.Sdk">
  <PropertyGroup>
    <TargetFrameworks>
      net8.0-browserwasm;
      net8.0-ios;
      net8.0-android;
      net8.0-maccatalyst;
      net8.0-windows10.0.19041;
      net8.0-desktop
    </TargetFrameworks>
    <OutputType>Exe</OutputType>
    <UnoFeatures>
      Extensions;
      Toolkit;
      Material;
      MVUX;
      Navigation;
      Configuration;
      Hosting;
      Http;
      Localization;
      Logging;
      LoggingSerilog;
      Serialization;
      Authentication;
      AuthenticationOidc
    </UnoFeatures>
  </PropertyGroup>
</Project>

UnoFeatures MSBuild プロパティは、含める Uno Extensions とテーマパッケージを制御します。Uno SDK はこれらの機能を適切な NuGet パッケージに自動的に解決します。

プロジェクトのレイアウト
MyApp/
  MyApp/
    App.xaml / App.xaml.cs        # Application entry, resource dictionaries
    MainPage.xaml / .xaml.cs      # Initial page
    Presentation/                 # ViewModels or MVUX Models
    Views/                        # XAML pages
    Services/                     # Service interfaces and implementations
    Strings/                      # Localization resources (.resw)
      en/Resources.resw
    Assets/                       # Images, fonts, icons
    appsettings.json              # Configuration (Extensions.Configuration)
    Platforms/                    # Platform-specific code (conditional compilation)
      Android/
      iOS/
      Wasm/
      Desktop/
  MyApp.Tests/                   # Unit tests (shared logic)

Uno Extensions

Uno Extensions は、プラットフォーム上に独自の方針を持つインフラストラクチャを提供します。すべてのモジュールはホストビルダーパターンを通じて登録します。

ホストビルダーのセットアップ
// App.xaml.cs
public App()
{
    this.InitializeComponent();

    Host = UnoHost
        .CreateDefaultBuilder()
        .UseConfiguration(configure: configBuilder =>
            configBuilder.EmbeddedSource<App>()
                         .Section<AppConfig>())
        .UseLocalization()
        .UseNavigation(RegisterRoutes)
        .UseSerilog(loggerConfiguration: config =>
            config.WriteTo.Debug())
        .ConfigureServices((context, services) =>
        {
            services.AddSingleton<IProductService, ProductService>();
        })
        .Build();
}
ナビゲーション

パッケージ: Uno.Extensions.Navigation

ルートマップ、ディープリンク、型安全なパラメーター受け渡しを備えた、リージョンベースのナビゲーションです。ナビゲーションは、XAML から宣言的に、またはコードから命令的に実行できます。

// Route registration
private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes)
{
    views.Register(
        new ViewMap(ViewModel: typeof(ShellModel)),
        new ViewMap<MainPage, MainModel>(),
        new ViewMap<ProductDetailPage, ProductDetailModel>(),
        new DataViewMap<ProductDetailPage, ProductDetailModel, ProductEntity>()
    );

    routes.Register(
        new RouteMap("", View: views.FindByViewModel<ShellModel>(),
            Nested: new RouteMap[]
            {
                new("Main", View: views.FindByViewModel<MainModel>()),
                new("ProductDetail", View: views.FindByViewModel<ProductDetailModel>())
            })
    );
}

<Button Content="View Product"
        uen:Navigation.Request="ProductDetail"
        uen:Navigation.Data="{Binding SelectedProduct}" />

主な概念: リージョンベースのナビゲーションでは、ビジュアルリージョン(Frame、NavigationView、TabBar)にナビゲーション動作を関連付けます。ルートマップでナビゲーショングラフを定義します。ディープリンクでは、WASM 用に URL をルートにマッピングします。

依存性注入

パッケージ: Uno.Extensions.Hosting

内部では Microsoft.Extensions.Hosting を使用します。サービス登録、キー付きサービス、スコープ付きライフタイムを備えたホストビルダーパターンです。

.ConfigureServices((context, services) =>
{
    // Standard DI registration
    services.AddSingleton<IAuthService, AuthService>();
    services.AddTransient<IOrderService, OrderService>();

    // Keyed services (.NET 8+)
    services.AddKeyedSingleton<ICache>("memory", new MemoryCache());
    services.AddKeyedSingleton<ICache>("distributed", new RedisCache());
})
構成

パッケージ: Uno.Extensions.Configuration

appsettings.json(埋め込みリソース)、環境固有のオーバーライド、実行時に書き込み可能なオプションから構成を読み込みます。

// appsettings.json
{
  "AppConfig": {
    "ApiBaseUrl": "https://api.example.com",
    "MaxRetries": 3
  }
}
// Binding to strongly-typed options
.UseConfiguration(configure: configBuilder =>
    configBuilder
        .EmbeddedSource<App>()
        .Section<AppConfig>())

// AppConfig.cs
public record AppConfig
{
    public string ApiBaseUrl { get; init; } = "";
    public int MaxRetries { get; init; } = 3;
}
シリアル化

パッケージ: Uno.Extensions.Serialization

AOT 互換性のためにソースジェネレーターを使用して System.Text.Json と統合します。Extensions エコシステム全体で JSON シリアル化を構成します。

.UseSerialization(configure: serializerBuilder =>
    serializerBuilder
        .AddJsonTypeInfo(AppJsonContext.Default.ProductDto)
        .AddJsonTypeInfo(AppJsonContext.Default.OrderDto))

一般的なシリアル化パターンと AOT ソース生成の詳細については、[skill:dotnet-serialization] を参照してください。

ローカライズ

パッケージ: Uno.Extensions.Localization

.resw ファイルを使用したリソースベースのローカライズで、実行時のカルチャ切り替えに対応します。

.UseLocalization()





<TextBlock x:Uid="MainPage_Title" />
<Button x:Uid="MainPage_LoginButton" />

実行時のカルチャ切り替え:

// Switch culture programmatically
var localizationService = serviceProvider.GetRequiredService<ILocalizationService>();
await localizationService.SetCurrentCultureAsync(new CultureInfo("fr-FR"));
ロギング

パッケージ: Uno.Extensions.Logging

Microsoft.Extensions.Logging と統合します。プラットフォーム固有のシンクには Serilog を統合できます。

.UseSerilog(loggerConfiguration: config =>
    config
        .MinimumLevel.Information()
        .WriteTo.Debug()
        .WriteTo.Console())

プラットフォーム固有のシンク:Desktop ではデバッグ出力、WASM ではブラウザーコンソール、Android ではプラットフォームの logcat、iOS では NSLog を使用します。

HTTP

パッケージ: Uno.Extensions.Http

エンドポイント構成を備えた HTTP クライアント統合です。型付き API クライアント向けの Refit と、OpenAPI から生成されるクライアント向けの Kiota に対応しています。

.UseHttp(configure: (context, services) =>
    services
        .AddRefitClient<IProductApi>(context,
            configure: builder => builder
                .ConfigureHttpClient(client =>
                    client.BaseAddress = new Uri("https://api.example.com"))))
// Refit interface
public interface IProductApi
{
    [Get("/products")]
    Task<List<ProductDto>> GetProductsAsync(CancellationToken ct = default);

    [Get("/products/{id}")]
    Task<ProductDto> GetProductByIdAsync(int id, CancellationToken ct = default);
}
認証

パッケージ: Uno.Extensions.Authentication

OIDC、カスタム認証プロバイダー、トークン管理を提供します。ナビゲーションと統合し、ログイン/ログアウトのフローを実現します。

.UseAuthentication(auth =>
    auth.AddOidc(oidc =>
    {
        oidc.Authority = "https://login.example.com";
        oidc.ClientId = "my-app";
        oidc.Scope = "openid profile email";
    }))

トークン管理は自動で行われます。トークンはプラットフォームごとに安全に保存され(iOS/macOS では Keychain、Android では KeyStore、Windows では Credential Manager、WASM ではブラウザーのストレージ)、透過的に更新されます。


MVUX(Model-View-Update-eXtended)

MVUX は Uno が推奨するリアクティブパターンで、MVVM とは異なります。不変レコード、Feed、State を使用して、データフローを宣言的にモデル化します。ソースジェネレーターにより、通常のモデルクラスからバインド可能なプロキシが生成されます。

コアコンセプト
概念目的MVVM における相当要素
ModelUI の状態を定義する不変レコードViewModel
Feed非同期データソース(読み込み/データ/エラーの状態)ObservableCollection + 読み込みフラグ
State変更を追跡する可変リアクティブ状態INotifyPropertyChanged プロパティ
ListFeedコレクションに特化した FeedObservableCollection
Commandパブリックな非同期メソッドから自動生成ICommand
Model の例
// ProductModel.cs -- MVUX model (source generators produce the bindable proxy)
public partial record ProductModel(IProductService ProductService)
{
    // Feed: async data source with loading/error/data states
    public IFeed<IImmutableList<ProductDto>> Products => Feed
        .Async(async ct => await ProductService.GetProductsAsync(ct));

    // State: mutable reactive value
    public IState<string> SearchTerm => State<string>.Value(this, () => "");

    // ListFeed with selection support
    public IListFeed<ProductDto> FilteredProducts => SearchTerm
        .SelectAsync(async (term, ct) =>
            await ProductService.SearchProductsAsync(term, ct))
        .AsListFeed();

    // Command: auto-generated from async method signature
    public async ValueTask AddProduct(CancellationToken ct)
    {
        var term = await SearchTerm;
        await ProductService.AddProductAsync(term, ct);
    }
}

<Page x:Class="MyApp.Views.ProductPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <StackPanel>
        <TextBox Text="{Binding SearchTerm, Mode=TwoWay}" />

        <FeedView Source="{Binding FilteredProducts}">
            <FeedView.ValueTemplate>
                <DataTemplate>
                    <ListView ItemsSource="{Binding Data}">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Name}" />
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </DataTemplate>
            </FeedView.ValueTemplate>
            <FeedView.ProgressTemplate>
                <DataTemplate>
                    <ProgressRing IsActive="True" />
                </DataTemplate>
            </FeedView.ProgressTemplate>
            <FeedView.ErrorTemplate>
                <DataTemplate>
                    <TextBlock Text="Error loading products" Foreground="Red" />
                </DataTemplate>
            </FeedView.ErrorTemplate>
        </FeedView>

        <Button Content="Add Product" Command="{Binding AddProduct}" />
    </StackPanel>
</Page>
MVUX と MVVM の比較
項目MVUXMVVM
Model の定義不変の record 型INotifyPropertyChanged を実装した可変クラス
データの読み込み読み込み/エラー状態を組み込みで備えた IFeed<T>手動での読み込みフラグと try/catch
コレクション不変スナップショットを持つ IListFeed<T>変更可能な ObservableCollection<T>
コマンドasync メソッドから自動生成ICommand の実装(RelayCommand)
状態の変更明示的な更新セマンティクスを持つ IState<T>PropertyChanged を発生させるプロパティセッター
定型コード最小限(ソースジェネレーター)多い(基底クラス、属性)

MVUX を使用する場合: 新しい Uno Platform プロジェクト、特に非同期データソースや複雑な読み込み状態を扱うプロジェクトに適しています。MVUX を使うと、定型コードの大部分をなくし、読み込み/エラー状態を宣言的に処理できます。

MVVM を使用する場合: 既存の WPF/UWP/WinUI コードベースから移行するプロジェクト、MVVM パターンに慣れたチーム、または CommunityToolkit.Mvvm を使用するプロジェクトに適しています。


Uno Toolkit コントロール

Uno Toolkit は、標準の WinUI コントロールに加えて、クロスプラットフォームのコントロールとヘルパーを提供します。UnoFeatures で Toolkit を指定して有効にします。

主なコントロール
コントロール目的
AutoLayout間隔、パディング、配置を設定できる Flexbox 風レイアウト
Card / CardContentControlエレベーションに対応した Material スタイルのカードサーフェス
Chip / ChipGroupフィルターチップ、アクションチップ、選択チップ
Divider水平/垂直の区切り線
DrawerControlサイドドロワー(ハンバーガーメニュー)
LoadingViewスケルトン/シマーに対応した読み込み状態のラッパー
NavigationBarクロスプラットフォームのナビゲーションバー
ResponsiveView画面幅のブレークポイントに応じたアダプティブレイアウト
SafeAreaノッチ、ステータスバー、ナビゲーションバー用のインセット
ShadowContainerThemeShadow によるクロスプラットフォームのドロップシャドウ
TabBar下部または上部のタブナビゲーション
ZoomContentControlピンチ操作で拡大縮小できるコンテナー
Toolkit ヘルパー
ヘルパー目的
CommandExtensionsButton 以外の任意のコントロールにコマンドをアタッチ
ItemsRepeaterExtensionsItemsRepeater の選択とコマンドをサポート
InputExtensions自動フォーカス、リターンキーコマンド、入力スコープ
ResponsiveMarkupExtensionsXAML マークアップでのレスポンシブ値(例:Responsive.Narrow)
StatusBarExtensionsプラットフォームごとのステータスバーの外観を制御
AncestorBindingテンプレート内で祖先の DataContext にバインド
AutoLayout の例

<utu:AutoLayout Spacing="16" Padding="24"
                PrimaryAxisAlignment="Start"
                CounterAxisAlignment="Stretch">

    <TextBlock Text="Product List"
               Style="{StaticResource HeadlineMedium}" />

    <utu:AutoLayout Spacing="8" Orientation="Horizontal">
        <TextBox PlaceholderText="Search..."
                 utu:AutoLayout.PrimaryLength="*" />
        <Button Content="Search"
                utu:AutoLayout.CounterAlignment="Center" />
    </utu:AutoLayout>

    <ListView ItemsSource="{Binding Products}"
              utu:AutoLayout.PrimaryLength="*" />
</utu:AutoLayout>

テーマリソース

Uno は、テーマパッケージとして Material、Cupertino、Fluent のデザインシステムをサポートしています。テーマを使用すると、すべてのプラットフォームで色、タイポグラフィ、エレベーション、コントロールのスタイルを統一できます。

テーマの構成

<UnoFeatures>Material</UnoFeatures>   

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            
            <MaterialTheme />

            
            <ResourceDictionary Source="ms-appx:///Themes/ColorPaletteOverride.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
色のカスタマイズ

ColorPaletteOverride.xaml を使って Material テーマの色を上書きします。


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Color x:Key="PrimaryColor">#6750A4</Color>
    <Color x:Key="SecondaryColor">#625B71</Color>
    <Color x:Key="TertiaryColor">#7D5260</Color>
    <Color x:Key="ErrorColor">#B3261E</Color>
</ResourceDictionary>
タイポグラフィ

テーマシステムの既存の TextBlock スタイルを使用します。明示的なフォントサイズは設定せず、Material のタイポグラフィスケールを使用してください。

<TextBlock Text="Headline" Style="{StaticResource HeadlineMedium}" />
<TextBlock Text="Body text" Style="{StaticResource BodyLarge}" />
<TextBlock Text="Caption" Style="{StaticResource LabelSmall}" />
スタイル主な用途
DisplayLarge/Medium/Smallヒーローテキスト、スプラッシュ画面
HeadlineLarge/Medium/Smallページタイトル、セクション見出し
TitleLarge/Medium/Smallカードタイトル、ダイアログタイトル
BodyLarge/Medium/Small段落テキスト、説明
LabelLarge/Medium/Smallボタンラベル、キャプション、メタデータ
ThemeService

プログラムからライトテーマとダークテーマを切り替えます。

var themeService = serviceProvider.GetRequiredService<IThemeService>();
await themeService.SetThemeAsync(AppTheme.Dark);
var currentTheme = themeService.Theme;

ホットリロード

Uno Platform は独自の実装により、すべてのターゲットでホットリロードを提供します。XAML と C# コードビハインドの変更は、アプリを再起動せずに反映されます。

サポートされる変更
変更の種類ホットリロードのサポート
XAML のレイアウト/スタイル完全なリロード、即時反映
C# コードビハインド(メソッド本体)MetadataUpdateHandler によるサポート
新しいプロパティ/メソッド再ビルドが必要
リソースディクショナリの変更完全なリロード
ナビゲーションルートの変更再ビルドが必要
ホットリロードの有効化
# Set environment variable before dotnet run
export DOTNET_MODIFIABLE_ASSEMBLIES=debug

# Run with Hot Reload
dotnet run -f net8.0-desktop --project MyApp/MyApp.csproj

ホットリロードは Visual Studio と VS Code(Uno 拡張機能を使用)で自動的に構成されます。CLI を使用する場合は、実行前に DOTNET_MODIFIABLE_ASSEMBLIES=debug を設定してください。

注意点: ホットリロードでは、新しい型の追加、継承階層の変更、UnoFeatures の変更はサポートされません。これらには完全な再ビルドが必要です。


エージェントが注意すべき点

  1. MVUX と MVVM を混同しないでください。 MVUX は不変レコード、Feeds、States を使用し、INotifyPropertyChanged は使用しません。MVUX モデルに ObservableProperty 属性を追加しないでください。
  2. Uno Extensions の NuGet パッケージバージョンをハードコードしないでください。 UnoFeatures MSBuild プロパティは、Uno SDK を通じてパッケージを自動的に解決します。Extensions の PackageReference 項目を明示的に追加すると、バージョンの競合が発生する可能性があります。
  3. Uno XAML では {Binding StringFormat=...} を使用しないでください。 これは WPF 専用の機能です。書式付きテキストには、コンバーターまたは複数の <Run> 要素を使用してください。
  4. バインディングで x:Static や {x:Reference} を使用しないでください。 これらは WPF 専用のマークアップ拡張機能であり、WinUI/Uno では使用できません。
  5. 明示的なフォントサイズやフォントウェイトを設定しないでください。 デザインシステムの一貫性を保つため、テーマの TextBlock スタイル(例:HeadlineMedium、BodyLarge)を使用してください。
  6. 16 進数カラーをハードコードしないでください。 テーマとの互換性を保つため、常にテーマリソース(PrimaryColor、SecondaryColor)またはセマンティックブラシを参照してください。
  7. CommandBar の外で AppBarButton を使用しないでください。 単独のアイコンボタンには、アイコンコンテンツを含む通常の Button を使用してください。
  8. ローカライズ用の x:Uid を忘れないでください。 ユーザーに表示される文字列はすべて、ハードコードされたテキストではなく、.resw リソースを参照する x:Uid を使用してください。

前提条件

  • .NET 8.0 以降(Uno Platform 5.x のベースライン)
  • Uno SDK(Uno.Sdk プロジェクト SDK)
  • 必要に応じたプラットフォームワークロード:dotnet workload install ios android maccatalyst wasm-tools
  • Visual Studio 2022 以降、または Uno Platform 拡張機能を備えた VS Code

参考資料

コメント