WPF と Xamarin.Forms: 類似点と相違点

コントロール テンプレート

WPF では、コントロール (ButtonListBox など) の視覚化命令を提供する "コントロール テンプレート" の概念がサポートされています。 前述のとおり、Xamarin.Forms では、ネイティブ プラットフォーム (iOS、Android など) と対話する具象 "レンダリング" クラスを使用してコントロールを視覚化します。

ただし、Xamarin.Forms には ControlTemplate 型が "あり"、Page オブジェクトのテーマ設定に使用されます。 これを使用すると、一貫したコンテンツを提供する Page を定義できますが、ページのユーザーは、色やフォントなどを変更できるだけでなく、要素を追加してアプリケーションに固有のページにすることもできます。

この一般的な用途としては、認証ダイアログやプロンプトなどがあります。また、標準化されているが、アプリ内でカスタマイズできるテーマ設定可能なページの外観を提供するためにも使用できます。 このサポートの一環として、使い慣れた WPF の名前を付けたコントロールが数多く使用されています。

  1. ContentPage
  2. ContentView
  3. ContentPresenter
  4. TemplateBinding

ただし、これらは Xamarin.Forms では同じ目的を "果たさない" ことを知っておくことが重要です。 この機能の詳細については、こちらのドキュメント ページを参照してください。

XAML

XAML は、WPF および Xamarin.Forms の宣言型マークアップ言語として使用されます。 ほとんどの場合、構文は同じです。主な違いは、XAML グラフによって定義または作成されるオブジェクトです。

  • Xamarin.Forms では XAML 2009 仕様がサポートされています。これにより、ジェネリック型の定義やコンストラクターへの引数の受け渡しだけでなく、stringint などのデータの定義も容易になります。

  • 現在、WPF で XamlReader を使用して実行できるように、XAML を動的に読み込む方法はありません。 ただし、NuGet パッケージで同じ基本機能を取得できます。

マークアップ拡張機能

Xamarin.Forms は、WPF と同様に、マークアップ拡張機能による XAML の拡張をサポートしています。 同じ基本的な構成要素が含まれており、すぐに使用できます。

  1. {x:Array}
  2. {Binding}
  3. {DynamicResource}
  4. {x:Null}
  5. {x:Static}
  6. {StaticResource}
  7. {x:Type}

さらに、XAML 2009 仕様の {x:Reference} と、Xamarin.Forms でサポートされる ControlTemplate の特殊なバージョンに使用される {TemplateBinding} マークアップ拡張機能が含まれています。

警告

ControlTemplate は、同じ名前であってもサポートは同じではありません。

Xamarin.Forms はカスタム マークアップ拡張機能もサポートしていますが、実装は若干異なります。 WPF では、抽象基本クラスである MarkupExtension から派生する必要があります。 Xamarin.Forms では、これはより柔軟なインターフェイス IMarkupExtension または IMarkupExtension<T> に置き換えられます。

WPF と同様に、必要なメソッドは 1 つあり、マークアップ拡張機能から値を返す ProvideValue メソッドです。

バインディング インフラストラクチャ

引き継がれている中心的な概念の 1 つは、ビジュアル プロパティを .NET データ プロパティに接続するためのデータ バインディング インフラストラクチャです。 これにより、MVVM などのアーキテクチャ パターンが有効になります。 基本的な設計は同じです。バインド可能な基底クラス BindableObject があります。WPF では、これは DependencyObject クラスです。 この基底クラスは、データ バインディングのターゲットとして参加するすべてのオブジェクトのルート先祖として使用されます。 次に、派生クラスは、プロパティ値のバッキング ストレージとして機能する BindableProperty オブジェクトを公開します (これらは、WPF では DependencyProperty オブジェクトとして定義されます)。

バインド可能プロパティの定義

Xamarin.Forms でのバインド可能なプロパティの定義は WPF と同じです。

  1. オブジェクトは、BindableObject から派生する必要があります。
  2. プロパティのバッキング ストレージ キーを定義するには、BindableProperty 型のパブリック静的フィールドが宣言されている必要があります。
  3. GetValueSetValue を使用してプロパティ値を取得および変更するパブリック インスタンス プロパティ ラッパーが必要です。

完全な例については、Xamarin.Forms のバインド可能プロパティに関するページを参照してください。

添付プロパティ

添付プロパティはバインド可能なプロパティのサブセットであり、WPF と同じように機能します。 主な違いは、この場合、プロパティ ラッパーが省略され、所有クラスの静的な get/set メソッドのセットに置き換えられる点です。 詳細については、Xamarin.Forms の添付プロパティに関するページを参照してください。

バインディング エンジンの使用

バインディング エンジンを使用するプロセスは、WPF の場合と同じです。 これは、ソース オブジェクト (任意の .NET 型) と省略可能なプロパティ値 (省略した場合、WPF と同様に、ソース オブジェクトがプロパティ自体として扱われます) に関連付けられた Binding オブジェクトを作成することにより、コードビハインドで利用できます。 その後、任意の BindableObjectSetBinding を使用して、バインディングを BindableProperty に関連付けることができます。

または、BindingExtension を使用して XAML でバインド関係を定義することもできます。 WPF の拡張機能と同じ基本値を持ちます。

バインディング サポートとエンジンは、WPF よりも Silverlight 実装に似ています。 Xamarin.Forms には実装されていなかったいくつかの不足している機能があります。

  • バインディングでは次の機能はサポートされていません。
    • BindingGroupName
    • BindsDirectlyToSource
    • IsAsync
    • MultiBinding
    • NotifyOnSourceUpdated
    • NotifyOnTargetUpdated
    • NotifyOnValidationError
    • UpdateSourceTrigger
    • UpdateSourceExceptionFilter
    • ValidatesOnDataErrors
    • ValidatesOnExceptions
    • ValidationRules collection
    • XPath
    • XmlNamespaceManager

RelativeSource

RelativeSource バインディングはサポートされていません。 WPF では、これらを使用すると、XAML で定義された他のビジュアル要素にバインドできます。 Xamarin.Forms では、{x:Reference} マークアップ拡張を使用して、この同じ機能を実現できます。 たとえば、Text プロパティを持つ "otherControl" という名前のコントロールがあると仮定すると、次のようにしてこれにバインドできます。

WPF

Text={Binding RelativeSource={RelativeSource otherControl}, Path=Text}

Xamarin.Forms

Text={Binding Source={x:Reference otherControl}, Path=Text}

同じ機能を {RelativeSource Self} 機能にも使用できます。 ただし、型 ({RelativeSource FindAncestor}) による先祖の検索はサポートされていません。

バインディング コンテキスト

WPF では、既定のバインディング ソースを表す DataContext プロパティ値を定義できます。 バインディングのソースが定義されていない場合は、このプロパティ値が使用されます。 値はビジュアル ツリーの下位に継承されるため、高いレベルで定義した後、子が使用できるようになります。

Xamarin.Forms では、この同じ機能を使用できますが、プロパティ名は BindingContext です。

値コンバーター

値コンバーターは、WPF と同様に、Xamarin.Forms でも完全にサポートされています。 同じインターフェイスの図形が使用されますが、Xamarin.Forms には、Xamarin.Forms 名前空間で定義されたインターフェイスがあります。

Model-View-ViewModel

MVVM は、WPF と Xamarin.Forms の両方で完全にサポートされています。

WPF には、時々使用される組み込みの RoutedCommand が含まれており、Xamarin.Forms には、ICommand インターフェイス定義以外の組み込みのコマンド サポートはありません。 さまざまな MVVM フレームワークを含めると、MVVM の実装に必要な基底クラスを追加することができます。

INotifyPropertyChanged と INotifyCollectionChanged

どちらのインターフェイスも、Xamarin.Forms バインディングで完全にサポートされています。 XAML ベースの多くのフレームワークとは異なり、プロパティ変更通知は Xamarin.Forms のバックグラウンド スレッドで発生させることができ (WPF と同様)、バインド エンジンは UI スレッドに適切に移行します。

さらに、どちらの環境でも、適切なスレッド マーシャリングを行うために SynchronizationContextasync/await がサポートされています。 WPF にはすべてのビジュアル要素に Dispatcher クラスが含まれており、Xamarin.Forms には静的メソッド Device.BeginInvokeOnMainThread があり、これも使用できます (ただし、クロスプラットフォーム コーディングには SynchronizationContext が推奨されます)。

  • Xamarin.Forms には、コレクション変更通知をサポートする ObservableCollection<T> が含まれています。
  • BindingBase.EnableCollectionSynchronization を使用して、コレクションのクロススレッド更新を有効にすることができます。 API は WPF バリエーションとは若干異なります。使用の詳細については、こちらのドキュメントを参照してください。

データ テンプレート

Xamarin.Forms では、ListView の行 (セル) のレンダリングをカスタマイズするために、データ テンプレートがサポートされます。 DataTemplate をコンテンツ指向の任意のコントロールに利用できる WPF とは異なり、Xamarin.Forms では現在、それらは ListView にのみ使用されます。 テンプレート定義は、インラインで (ItemTemplate プロパティに割り当てて) 定義することも、ResourceDictionary 内のリソースとして定義することもできます。

さらに、データ テンプレートは、WPF の対応する機能ほど柔軟ではありません。

  1. DataTemplate のルート要素は、"常に" ViewCell オブジェクトである必要があります。
  2. データ トリガーはデータ テンプレートでサポートされていますが、そのトリガーが関連付けられているプロパティの型を指示する DataType プロパティが含まれている必要があります。
  3. DataTemplateSelector もサポートされていますが、DataTemplate から派生するため、ItemTemplate プロパティに直接割り当てられます (WPF では ItemTemplateSelector)。

ItemsControl

Xamarin.Forms には、ItemsControl に相当する組み込みの機能はありません。ただし、Xamarin.Forms 用のカスタムの ItemsControl があり、こちらから入手できます。

ユーザー コントロール

WPF では、関連付けられた動作がある UI のセクションを提供するために UserControl を使用します。 Xamarin.Forms では、同じ目的に ContentView を使用します。 どちらも、XAML でのバインドと包含をサポートします。

WPF には、"ブラウザーに似た" ナビゲーション機能を提供するために使用できる NavigationService が含まれていますが、ほとんど使用されません。 ただし、ほとんどのアプリでは、これが問題になることはなく、代わりに別の Window 要素、またはウィンドウの別のセクションを使用してデータを表示しています。

電話デバイスでは、異なる "画面" が解決策となることが多いため、Xamarin.Forms では、複数の形式のナビゲーションがサポートされています。

ナビゲーション スタイル ページの種類
スタックベース (プッシュまたはポップ) NavigationPage
マスター/詳細 MasterDetailPage
タブ TabbedPage
左右のスワイプ CarouselView

NavigationPage は最も一般的なアプローチであり、すべてのページには Navigation プロパティがあります。これを使用して、ナビゲーション スタックとの間でページをプッシュまたはポップすることができます。 これは、WPF にある NavigationService に最も近い機能です。

URL ナビゲーション

WPF はデスクトップ指向のテクノロジであり、スタートアップ動作を指示するコマンド ライン パラメータを受け入れることができます。 Xamarin.Forms はディープ URL リンクを使用して、スタートアップ ページにジャンプできます。