WPF とXamarin.Forms アプリのライフサイクル
Xamarin.Forms は、その前に登場した XAML ベースのフレームワーク、特に WPF から多くの設計ガイダンスを取得しています。 ただし、他の点では大きく異なっており、移行しようとしているユーザーにとって厄介な問題になる可能性があります。 このドキュメントでは、これらの問題のいくつか特定し、可能な限り WPF の知識を Xamarin.Forms に引き継げるようにするガイダンスを提供します。
アプリのライフサイクル
WPF と Xamarin.Forms の間のアプリケーション のライフサイクルは似ています。 どちらも外部 (プラットフォーム) コードで開始され、メソッド呼び出しを使用して UI を起動します。 違いは、Xamarin.Forms は常にプラットフォーム固有のアセンブリで開始され、その後、アプリの UI が初期化されて作成される点です。
WPF
Main method > App > MainWindow
Note
Main
メソッドは、既定では自動生成され、コードには表示されません。
Xamarin.Forms
- iOS –
Main method > AppDelegate > App > ContentPage
- Android –
MainActivity > App > ContentPage
- UWP –
Main method > App(UWP) > MainPage(UWP) > App > ContentPage
アプリケーション クラス
WPF と Xamarin.Forms の両方に、シングルトンとして作成される Application
クラスがあります。 ほとんどの場合、アプリはこのクラスから派生してカスタム アプリケーションを提供しますが、これは WPF では厳密には必要ありません。 どちらも、作成されたシングルトンを見つけるための Application.Current
プロパティを公開します。
グローバル プロパティ + 永続化
WPF と Xamarin.Forms の両方に、アプリケーション内の任意の場所からアクセスできるグローバル アプリ レベルのオブジェクトを保存できる Application.Properties
ディクショナリがあります。 主な違いは、Xamarin.Forms は、アプリが中断されたときにコレクションに保存されているすべてのプリミティブ型を "保持" し、再起動時にそれらを再読み込みすることです。 WPF では、その動作は自動的にはサポートされません。代わりに、ほとんどの開発者は分離ストレージに依存しているか、組み込みの Settings
サポートを利用していました。
ページとビジュアル ツリーの定義
WPF では、最上位のビジュアル要素のルート要素として Window
が使用されます。 これにより、Windows の世界で情報を表示する HWND が定義されます。 WPF では、必要な数のウィンドウを同時に作成して表示できます。
Xamarin.Forms では、最上位のビジュアルは常にプラットフォームによって定義されます。たとえば、iOS では UIWindow
です。 Xamarin.Forms は、Page
クラスを使用して、そのコンテンツをこれらのネイティブ プラットフォーム表現にレンダリングします。 Xamarin.Forms 内の各 Page
は、アプリケーション内の一意の "ページ" を表します。この場合、一度に表示できるのは 1 つだけです。
WPF の Window
と Xamarin.Forms の Page
の両方に、表示されるタイトルに影響を与える Title
プロパティが含まれており、両方にページの特定のアイコンを表示する Icon
プロパティがあります (注: タイトルとアイコンが Xamarin.Forms で常に表示されるとは限りません)。 また、両方で、背景色や画像などの共通のビジュアル プロパティを変更できます。
技術的には、2 つの個別のプラットフォーム ビューにレンダリングすることは可能ですが (たとえば、2 つの UIWindow
オブジェクトを定義し、2 つ目のオブジェクトを外部ディスプレイまたは AirPlay にレンダリングする)、それにはプラットフォーム固有のコードが必要であり、Xamarin.Forms 自体で直接サポートされている機能ではありません。
ビュー
両方のフレームワークのビジュアル階層は似ています。 WPF は、WYSIWYG ドキュメントをサポートしているため、少し深くなります。
WPF
DependencyObject - base class for all bindable things
Visual - rendering mechanics
UIElement - common events + interactions
FrameworkElement - adds layout
Shape - 2D graphics
Control - interactive controls
Xamarin.Forms
BindableObject - base class for all bindable things
Element - basic parent/child support + resources + effects
VisualElement - adds visual rendering properties (color, fonts, transforms, etc.)
View - layout + gesture support
ビュー ライフサイクル
Xamarin.Forms は、主にモバイル シナリオを対象としています。 そのため、アプリケーションは、ユーザーによる操作に応じて、"アクティブ化"、"中断"、"再アクティブ化" されます。 これは、WPF アプリケーションで Window
からクリックすることと同様であり、この動作を監視するためにオーバーライドまたはフックできる一連のメソッドおよび対応するイベントがあります。
目的 | WPF メソッド | Xamarin.Forms メソッド |
---|---|---|
初期アクティブ化 | ctor + Window.OnLoaded | ctor + Page.OnStart |
0 個中 | Window.IsVisibleChanged | Page.Appearing |
非表示 | Window.IsVisibleChanged | Page.Disappearing |
中断/フォーカスの喪失 | Window.OnDeactivated | Page.OnSleep |
アクティブ化/フォーカスの取得 | Window.OnActivated | Page.OnResume |
クローズ済みです | Window.OnClosing + Window.OnClosed | 該当なし |
どちらも子コントロールの非表示と表示もサポートしており、WPF では、これは 3 つの状態のプロパティ IsVisible
(表示、非表示、折りたたみ) です。 Xamarin.Forms では、IsVisible
プロパティを通じた表示または非表示のみです。
Layout
ページ レイアウトは、WPF と同じように 2 パス (測定/配置) で行われます。 Xamarin.Forms Page
クラスで次のメソッドをオーバーライドすることで、ページ レイアウトにフックできます。
メソッド | 目的 |
---|---|
OnChildMeasureInvalidated | 子の推奨サイズが変更されました。 |
OnSizeAllocated | ページに幅/高さが割り当てられました。 |
LayoutChanged イベント | ページのレイアウト/サイズが変更されました。 |
現在、呼び出されるグローバル レイアウト イベントはありません。また、WPF にあるようなグローバル CompositionTarget.Rendering
イベントもありません。
共通のレイアウト プロパティ
WPF と Xamarin.Forms は両方とも、要素の周りの間隔を制御する Margin
、および要素の "中" の間隔を制御する Padding
をサポートしています。 さらに、ほとんどの Xamarin.Forms レイアウト ビューには、間隔 (行や列など) を制御するプロパティがあります。
さらに、ほとんどの要素には、親コンテナー内での配置方法に影響を与える次のようなプロパティがあります。
WPF | Xamarin.Forms | 目的 |
---|---|---|
HorizontalAlignment | HorizontalOptions | Left/Center/Right/Stretch オプション |
VerticalAlignment | VerticalOptions | Top/Center/Bottom/Stretch オプション |
Note
これらのプロパティの実際の解釈は、親コンテナーによって異なります。
レイアウト ビュー
WPF と Xamarin.Forms はどちらも、レイアウト コントロールを使用して子要素を配置します。 ほとんどの場合、これらは機能の点で互いに非常に似ています。
WPF | Xamarin.Forms | レイアウト スタイル |
---|---|---|
StackPanel | StackLayout | 左から右、または上から下への無限積み重ね |
グリッド | グリッド | 表形式 (行と列) |
DockPanel | 該当なし | ウィンドウの端にドッキングする |
Canvas | AbsoluteLayout | ピクセル/座標の配置 |
WrapPanel | 該当なし | 折り返しスタック |
該当なし | RelativeLayout | 相対ルール ベースの配置 |
Note
Xamarin.Forms は、GridSplitter
をサポートしていません。
どちらのプラットフォームも、"添付プロパティ" を使用して子を微調整します。
表示
WPF と Xamarin.Forms のレンダリングのしくみは大きく異なります。 WPF では、作成したコントロールが、画面上のピクセルにコンテンツを直接レンダリングします。 WPF は、これを表すために 2 つのオブジェクトグラフ("ツリー")を保持します。"論理ツリー" は、コードまたは XAML で定義されたコントロールを表し、"ビジュアル ツリー" は、ビジュアル要素によって (仮想描画メソッドを使用して) 直接、または置換やカスタマイズが可能な XAML で定義された ControlTemplate
を介して実行される、スクリーン上で発生する実際のレンダリングを表します。 通常、ビジュアル ツリーは、コントロールの周囲の境界線や、暗黙的なコンテンツのラベルなどを含むため、より複雑です。WPF には、これら 2 つのオブジェクト グラフを調べるための一連の API (LogicalTreeHelper
と VisualTreeHelper
) が含まれています。
Xamarin.Forms では、Page
で定義するコントロールは、実際には単純なデータ オブジェクトに過ぎません。 これらは論理ツリー表現に似ていますが、コンテンツを単独でレンダリングすることはありません。 これらは、要素のレンダリングに影響を与える "データ モデル" です。 実際のレンダリングは、各コントロールの種類にマップされる "ビジュアル レンダラー" の個別のセット によって行われます。 これらのレンダラーは、プラットフォーム固有の Xamarin.Forms アセンブリによってプラットフォーム固有の各プロジェクトに登録されます。 ここで一覧を確認できます。. Xamarin.Forms では、レンダラーの置換や拡張に加えて、プラットフォームごとのネイティブ レンダリングに影響を与えるために使用できるエフェクトもサポートされています。
論理/ビジュアル ツリー
Xamarin.Forms の論理ツリーをたどるための公開された API はありませんが、リフレクションを使用して同じ情報を取得できます。 たとえば、リフレクションを使用して論理的な子を列挙できるメソッドをこちらに示します。
グラフィックス
Xamarin.Forms には、Shapes と呼ばれる、プリミティブを描画するためのグラフィックス システムが含まれています。 Shapes の詳細については、「Xamarin.Forms 図形」を参照してください。 さらに、SkiaSharp などのサード パーティ製ライブラリを含めて、クロスプラットフォームの 2D 描画を取得することもできます。
リソース
WPF と Xamarin.Forms の両方に、リソースとリソース ディクショナリの概念があります。 任意のオブジェクト型をキーを持つ ResourceDictionary
に配置し、変更されないものについては {StaticResource}
を、実行時にディクショナリで変更可能なものについては {DynamicResource}
を使用してそれを検索できます。 使用方法と仕組みは同じですが、違いが 1 つあります。Xamarin.Forms では、Resources
プロパティに割り当てる ResourceDictionary
をユーザーが定義する必要がありますが、WPF では自動でそれを事前作成して割り当てます。
たとえば、次の定義を参照してください。
WPF
<Window.Resources>
<Color x:Key="redColor">#ff0000</Color>
...
</Window.Resources>
Xamarin.Forms
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="redColor">#ff0000</Color>
...
</ResourceDictionary>
</ContentPage.Resources>
ResourceDictionary
を定義しない場合は、ランタイム エラーが生成されます。
スタイル
スタイルは Xamarin.Forms でも完全にサポートされており、UI を構成する Xamarin.Forms 要素のテーマを設定するために使用できます。 これは、トリガー (プロパティ、イベント、データ)、BasedOn
による継承、および値のリソース検索をサポートしています。 スタイルは、WPF と同様に、Style
プロパティを通じて明示的に、またはリソース キーを指定しないことで暗黙的に要素に適用されます。
デバイスのスタイル
WPF には、システムの色、フォント、メトリックを値とリソース キーの形式で指定する定義済みのプロパティのセット (SystemColors
などの静的クラスのセットに静的値として保存されます) があります。 Xamarin.Forms も同様ですが、同じものを表すためにデバイス スタイルのセットを定義します。 これらのスタイルはフレームワークによって提供され、ランタイム環境 (アクセシビリティなど) に基づいた値に設定されます。
WPF
<Label Text="Title" Foreground="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" />
Xamarin.Forms
<Label Text="Title" Style="{DynamicResource TitleStyle}" />