dotnet-uno-platform について
Uno Platform 5.x と .NET 8.0 以降のプロジェクト向け開発スキルで、アプリ構成、Extensions、MVUX、コントロール、テーマ、Hot Reload を扱います。Uno アプリの開発者を対象とし、ターゲット別のデプロイではなく共通のプロジェクト開発に重点を置きます。
主な機能
- 01単一プロジェクトのマルチターゲット構成
- 02ナビゲーションとサービス向け Extensions
- 03MVUX によるリアクティブなアプリ設計
- 04Toolkit のコントロールとヘルパー
- 05Material・Cupertino・Fluent テーマ
- 06XAML と C# の Hot Reload
活用シーン
- 01新しい Uno Platform アプリの構成
- 02リアクティブなデータフローとナビゲーションの追加
- 03Toolkit でアダプティブ UI を構築
- 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 における相当要素 |
|---|---|---|
| Model | UI の状態を定義する不変レコード | ViewModel |
| Feed | 非同期データソース(読み込み/データ/エラーの状態) | ObservableCollection + 読み込みフラグ |
| State | 変更を追跡する可変リアクティブ状態 | INotifyPropertyChanged プロパティ |
| ListFeed | コレクションに特化した Feed | ObservableCollection |
| 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 の比較
| 項目 | MVUX | MVVM |
|---|---|---|
| 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 | ノッチ、ステータスバー、ナビゲーションバー用のインセット |
ShadowContainer | ThemeShadow によるクロスプラットフォームのドロップシャドウ |
TabBar | 下部または上部のタブナビゲーション |
ZoomContentControl | ピンチ操作で拡大縮小できるコンテナー |
Toolkit ヘルパー
| ヘルパー | 目的 |
|---|---|
CommandExtensions | Button 以外の任意のコントロールにコマンドをアタッチ |
ItemsRepeaterExtensions | ItemsRepeater の選択とコマンドをサポート |
InputExtensions | 自動フォーカス、リターンキーコマンド、入力スコープ |
ResponsiveMarkupExtensions | XAML マークアップでのレスポンシブ値(例: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 の変更はサポートされません。これらには完全な再ビルドが必要です。
エージェントが注意すべき点
- MVUX と MVVM を混同しないでください。 MVUX は不変レコード、Feeds、States を使用し、
INotifyPropertyChangedは使用しません。MVUX モデルにObservableProperty属性を追加しないでください。 - Uno Extensions の NuGet パッケージバージョンをハードコードしないでください。
UnoFeaturesMSBuild プロパティは、Uno SDK を通じてパッケージを自動的に解決します。Extensions のPackageReference項目を明示的に追加すると、バージョンの競合が発生する可能性があります。 - Uno XAML では
{Binding StringFormat=...}を使用しないでください。 これは WPF 専用の機能です。書式付きテキストには、コンバーターまたは複数の<Run>要素を使用してください。 - バインディングで
x:Staticや{x:Reference}を使用しないでください。 これらは WPF 専用のマークアップ拡張機能であり、WinUI/Uno では使用できません。 - 明示的なフォントサイズやフォントウェイトを設定しないでください。 デザインシステムの一貫性を保つため、テーマの TextBlock スタイル(例:
HeadlineMedium、BodyLarge)を使用してください。 - 16 進数カラーをハードコードしないでください。 テーマとの互換性を保つため、常にテーマリソース(
PrimaryColor、SecondaryColor)またはセマンティックブラシを参照してください。 CommandBarの外でAppBarButtonを使用しないでください。 単独のアイコンボタンには、アイコンコンテンツを含む通常のButtonを使用してください。- ローカライズ用の
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