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

  • iOSMain method > AppDelegate > App > ContentPage
  • AndroidMainActivity > App > ContentPage
  • UWPMain 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 (LogicalTreeHelperVisualTreeHelper) が含まれています。

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}" />