次の方法で共有


Windows データ バインディングの詳細

この記事では、 Microsoft.UI.Xaml.Data 名前空間の API を使用した WinUI データ バインディング機能について説明します。

このトピックでは、データ バインディング機能について詳しく説明します。 簡単で実用的な概要については、「 データ バインディングの概要」を参照してください。

重要な API

イントロダクション

データ バインディングは、アプリの UI でデータを効率的に表示および同期できるようにする手法です。 データの懸念事項を UI の問題から分離することで、アプリの設計が簡素化され、読みやすさが向上し、保守容易性が向上します。

データ バインディングを使用すると、UI が最初に表示されたときにデータ ソースの値を表示するだけで、それらの値の変更には応答できません。 このバインド モードは 1 回限りと呼ばれ、実行時に変更されない値に適しています。 または、値を "観察" し、変更されたときに UI を更新することもできます。 このモードは 一方向と呼ばれ、読み取り専用データに適しています。 最終的には、観察と更新の両方を選択して、ユーザーが UI の値に加える変更が自動的にデータ ソースにプッシュバックされるようにすることができます。 このモードは 双方向と呼ばれ、読み取り/書き込みデータに適しています。 いくつかの例を次に示します。

  • 1 回限りのモードを使用して、 イメージ を現在のユーザーの写真にバインドできます。
  • 一方向モードを使用すると、 ListView を新聞セクション別にグループ化されたリアルタイムニュース記事のコレクションにバインドできます。
  • 双方向モードを使用して、フォーム内の顧客の名前に TextBox をバインドできます。

モードに依存せず、2 種類のバインディングがあり、通常は両方を UI マークアップで宣言します。 {x:Bind} マークアップ拡張または {Binding} マークアップ拡張のいずれかを使用できます。 同じ UI 要素でも、同じアプリで 2 つの組み合わせを使用することもできます。 {x:Bind} は Windows 10 用 UWP の新機能であり、パフォーマンスが向上しました。 特に明記しない限り、このトピックで説明するすべての詳細は、両方の種類のバインディングに適用されます。

{x:Bind} を示す UWP サンプル アプリ

{Binding} を示す UWP サンプル アプリ

すべてのバインディングには、これらの部分が含まれます

  • バインディング ソース。 このソースは、バインディングのデータを提供します。 UI に表示する値を持つメンバーを持つ任意のクラスのインスタンスを指定できます。
  • バインディング ターゲット。 このターゲットは、データを表示する UI の FrameworkElementDependencyProperty です。
  • バインド オブジェクト。 このオブジェクトは、ソースからターゲットにデータ値を転送し、必要に応じてターゲットからソースに戻します。 バインド オブジェクトは、 {x:Bind} または {Binding} マークアップ拡張から XAML 読み込み時 作成されます。

以降のセクションでは、バインディング ソース、バインド ターゲット、およびバインド オブジェクトについて詳しく説明します。 セクションは、ボタンのコンテンツを、NextButtonText という名前のクラスに属する HostViewModel という名前の文字列プロパティにバインドする例と共にリンクします。

バインディング ソース

バインディング ソースとして使用できるクラスの基本的な実装を次に示します。

public class HostViewModel
{
    public HostViewModel()
    {
        NextButtonText = "Next";
    }

    public string NextButtonText { get; set; }
}

HostViewModelの実装とそのプロパティNextButtonTextは、1 回限りのバインドでのみ機能します。 しかし、一方向と双方向のバインディングは非常に一般的であることがよくあります。 このようなバインドでは、バインディング ソースのデータ値の変更に応じて UI が自動的に更新されます。 このようなバインドが正しく機能するためには、バインディング ソースをバインディング オブジェクトに 対して監視できるようにする 必要があります。 したがって、この例では、 NextButtonText プロパティに対して一方向または双方向のバインドを行う場合は、実行時にそのプロパティの値に対する変更をバインディング オブジェクトに対して監視できる必要があります。

これを行う方法の 1 つは、 DependencyObject からバインディング ソースを表すクラスを派生させ、 DependencyProperty* を介してデータ値を公開することです。 FrameworkElement が監視可能になるのは、その方法です。 FrameworkElementは、すぐに使用する適切なバインディング ソースです。

クラスを監視可能にするより軽量な方法であり、既に基底クラスを持つクラスに必要な方法は、 System.ComponentModel.INotifyPropertyChanged を実装することです。 この方法では、 PropertyChangedという名前の 1 つのイベントを実装します。 HostViewModelを使用する例を次のコードに示します。

...
using System.ComponentModel;
using System.Runtime.CompilerServices;
...
public class HostViewModel : INotifyPropertyChanged
{
    private string nextButtonText;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public HostViewModel()
    {
        NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return nextButtonText; }
        set
        {
            nextButtonText = value;
            OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

これで、 NextButtonText プロパティが監視可能になりました。 そのプロパティに対して一方向または双方向のバインドを作成すると (後で説明します)、結果のバインド オブジェクトは PropertyChanged イベントをサブスクライブします。 そのイベントが発生すると、バインディング オブジェクトのハンドラーは、変更されたプロパティの名前を含む引数を受け取ります。 このように、バインディング オブジェクトは、再び読み取るプロパティの値を認識します。

前に複数回示したパターンを実装する必要がないように、C# を使用している場合は、BindableBase サンプル ("Common" フォルダー内) にある基底クラスから派生させることができます。 その外観の例を次に示します。

public class HostViewModel : BindableBase
{
    private string nextButtonText;

    public HostViewModel()
    {
        NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return nextButtonText; }
        set { SetProperty(ref nextButtonText, value); }
    }
}

PropertyChanged または を指定して null イベントを発生させると、オブジェクトのすべての非インデクサー プロパティを再読み取りする必要があることを示します。 イベントを発生させて、オブジェクトのインデクサー プロパティが変更されたことを示すには、特定のインデクサー (インデクサーがインデックス値である場合) に "Item[インデクサー]" の引数を使用するか、すべてのインデ クサー に対して値 "Item[]" を使用します。

バインディング ソースは、プロパティにデータが含まれる単一のオブジェクトとして、またはオブジェクトのコレクションとして扱うことができます。 C# コードでは、 List<T> を実装するオブジェクトに 1 回限りバインドして、実行時に変更されないコレクションを表示できます。 監視可能なコレクションの場合 (コレクションに項目が追加され、コレクションから削除されたときの監視)、代わりに ObservableCollection<T> に一方向バインドします。 独自のコレクション クラスにバインドするには、次の表のガイダンスを使用します。

Scenario C# (CLR) C++/WinRT
オブジェクトにバインドします。 任意のオブジェクトを指定できます。 任意のオブジェクトを指定できます。
バインドされたオブジェクトからプロパティ変更通知を取得します。 オブジェクトは INotifyPropertyChanged を実装する必要があります。 オブジェクトは INotifyPropertyChanged を実装する必要があります。
コレクションにバインドします。 List<T> IVectorIInspectable または IBindableObservableVectorXAML 項目コントロールを参照し、C++/WinRT コレクションと C++/WinRT使用してコレクションにバインドします。
バインドされたコレクションからコレクション変更通知を取得します。 ObservableCollection<T> IObservableVectorIInspectable? たとえば、winrt::single_threaded_observable_vector<T>
バインディングをサポートするコレクションを実装します。 List<T> を拡張するか、IListIList<Object>、IEnumerable、または IEnumerable<Object> を実装します。 汎用 IList<T>IEnumerable<T> へのバインドはサポートされていません。 IInspectableIVector を実装します。 XAML 項目コントロールを参照し、C++/WinRT コレクションと C++/WinRT使用してコレクションにバインドします。
コレクション変更通知をサポートするコレクションを実装します。 ObservableCollection<T> を拡張するか、(非ジェネリック) IListINotifyCollectionChanged を実装します。 IInspectableIObservableVector を実装するか、IBindableObservableVector を実装してください。
増分読み込みをサポートするコレクションを実装します。 ObservableCollection<T> を拡張するか、(非ジェネリック) IListINotifyCollectionChanged を実装します。 さらに、 ISupportIncrementalLoading を実装します IInspectable または IBindableObservableVectorIObservableVector を実装します。 さらに、 ISupportIncrementalLoading を実装します

増分読み込みを使用して、リスト コントロールを任意の大きなデータ ソースにバインドし、高いパフォーマンスを実現できます。 たとえば、一度にすべての結果を読み込む必要なく、リスト コントロールをBingイメージ クエリ結果にバインドできます。 代わりに、一部の結果のみをすぐに読み込み、必要に応じて追加の結果を読み込みます。 増分読み込みをサポートするには、コレクション変更通知をサポートするデータ ソースに ISupportIncrementalLoading を実装する必要があります。 データ バインディング エンジンがより多くのデータを要求する場合、データ ソースは適切な要求を行い、結果を統合してから、UI を更新するために適切な通知を送信する必要があります。

バインディング ターゲット

次の 2 つの例では、 Button.Content プロパティがバインディング ターゲットです。 その値は、バインディング オブジェクトを宣言するマークアップ拡張に設定されます。 最初の例は {x:Bind} を示し、2 番目の例は {Binding} を示しています。 マークアップでのバインドの宣言は、便利で読みやすく、ツール可能であるため、一般的なケースです。 ただし、必要に応じて、マークアップを回避し、代わりに Binding クラスのインスタンスを (プログラムによって) 強制的に作成できます。

<Button Content="{x:Bind ...}" ... />
<Button Content="{Binding ...}" ... />

C++/WinRT を使用している場合は、{Binding} マークアップ拡張を使用するランタイム クラスに BindableAttribute 属性を追加する必要があります。

Important

C++/WinRT を使用している場合は、Windows App SDK で BindableAttribute 属性を使用できます。 この属性がない場合、{Binding} マークアップ拡張を使用できるようにするには、ICustomPropertyProvider インターフェイスと ICustomProperty インターフェイスを実装する必要があります。

{x:Bind} を使用して宣言されたバインド オブジェクト

{x:Bind} マークアップを作成する前に、マークアップのページを表すクラスからバインディング ソース クラスを公開する必要があります。 (この場合は HostViewModel 型の) プロパティを MainWindow ウィンドウ クラスに追加します。

namespace DataBindingInDepth
{
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
            ViewModel = new HostViewModel();
        }
    
        public HostViewModel ViewModel { get; set; }
    }
}

プロパティを追加した後は、バインディング オブジェクトを宣言するマークアップを詳しく見ることができます。 次の例では、前の「バインド ターゲット」セクションで確認したのと同じ Button.Content バインド ターゲットを使用します。 HostViewModel.NextButtonText プロパティにバインドされているバインド ターゲットを示します。

<!-- MainWindow.xaml -->
<Window x:Class="DataBindingInDepth.MainWindow" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Window>

Pathに指定した値に注目してください。 ウィンドウは、独自のコンテキストでこの値を解釈します。 この場合、パスは、ViewModel ページに追加したMainWindow プロパティを参照することから始まります。 このプロパティは HostViewModel インスタンスを返します。そのため、そのオブジェクトに ドット を付けて、 HostViewModel.NextButtonText プロパティにアクセスできます。 Mode の既定値の 1 回限りをオーバーライドするを指定します。

Path プロパティは、入れ子になったプロパティ、添付プロパティ、整数および文字列インデクサーにバインドするためのさまざまな構文オプションをサポートしています。 詳細については、「 プロパティ パスの構文」を参照してください。 文字列インデクサーにバインドすると、 ICustomPropertyProvider を実装しなくても、動的プロパティにバインドする効果が得られます。 その他の設定については、 {x:Bind} マークアップ拡張を参照してください。

HostViewModel.NextButtonText プロパティが監視可能であることを示すために、ボタンにClick イベント ハンドラーを追加し、HostViewModel.NextButtonTextの値を更新します。 ビルドして実行し、ボタンをクリックして、ボタンの Content 更新の値を確認します。

// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    ViewModel.NextButtonText = "Updated Next button text";
}

TextBox.Text に対する変更は、TextBox がフォーカスを失ったときに双方向のバインドされたソースに送信されます。すべてのユーザー キーストロークの後に送信されるわけではありません。

DataTemplate と x:DataType

DataTemplate 内 (項目テンプレート、コンテンツ テンプレート、ヘッダー テンプレートのいずれとして使用する場合でも)、Pathの値はウィンドウのコンテキストでは解釈されません。 代わりに、テンプレート化するデータ オブジェクトのコンテキストで動作します。 データ テンプレートで {x:Bind} を使用すると、コンパイル時にそのバインドを検証し、効率的なコードを生成できます。 これを行うには、 DataTemplate は、 x:DataTypeを使用してデータ オブジェクトの型を宣言する必要があります。 次の例は、SampleDataGroup オブジェクトのコレクションにバインドされた項目コントロールのItemTemplateとして使用できます。

<DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

Path 内の弱く型指定されたオブジェクト

SampleDataGroupという名前の文字列プロパティを実装する Title という名前の型があるとします。 MainWindow.SampleDataGroupAsObject型のプロパティobjectもありますが、実際にはSampleDataGroupのインスタンスを返します。 バインド<TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/>Title型にobjectプロパティが見つからないため、コンパイル エラーが発生します。 このエラーを修正するには、次のように Path 構文にキャストを追加します: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>Elementobjectとして宣言されているが、実際にはTextBlockである別の例を次に示<TextBlock Text="{x:Bind Element.Text}"/>。 キャストによって、 <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>という問題が修正されます。

データが非同期的に読み込まれる場合

Windows の部分クラスは、コンパイル時に {x:Bind} をサポートするコードを生成します。 これらのファイルは、(C# の場合) objのような名前で、<view name>.g.cs フォルダーにあります。 生成されたコードには、ウィンドウの Loading イベントのハンドラー 含まれています。 そのハンドラーは、ウィンドウのバインドを表す生成されたクラスに対して Initialize メソッドを呼び出します。 InitializeUpdate を呼び出して、バインディング ソースとターゲットの間でデータの移動を開始します。 Loading は、ウィンドウまたはユーザー コントロールの最初のメジャー パスの直前に発生します。 データが非同期的に読み込まれる場合は、 Initialize 呼び出される時点で準備ができていない可能性があります。 データを読み込んだ後は、 this.Bindings.Update();を呼び出すことによって、1 回限りのバインドを強制的に初期化できます。 非同期に読み込まれたデータに対して 1 回限りバインドが必要な場合は、一方向バインディングを使用して変更をリッスンするよりも、このように初期化する方がはるかに低コストです。 データがきめ細かい変更を受けず、特定のアクションの一部として更新される可能性が高い場合は、バインドを 1 回だけ行い、 Updateの呼び出しでいつでも手動更新を強制できます。

{x:Bind} は、JSON オブジェクトのディクショナリ構造の操作や、ダックタイピングのような遅延バインディングのシナリオには適していません。 "Duck typing" は、プロパティ名に対する字句の一致に基づく弱い型指定です (たとえば、"歩く、泳ぐ、アヒルのようにクワックする場合、それはアヒルです")。 アヒル型指定では、 Age プロパティへのバインドは、 Person または Wine オブジェクトと同じように満たされます (これらの型にそれぞれ Age プロパティがあると仮定します)。 これらのシナリオでは、 {Binding} マークアップ拡張機能を使用します。

{Binding} を使用して宣言されたバインド オブジェクト

C++/WinRT を使用する場合は、{Binding} マークアップ拡張を使用するときにバインドするランタイム クラスに BindableAttribute 属性を追加します。 {x:Bind} を使用するには、その属性は必要ありません。

// HostViewModel.idl
// Add this attribute:
[Microsoft.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
    HostViewModel();
    String NextButtonText;
}

Important

C++/WinRT を使用している場合は、Windows App SDK で BindableAttribute 属性を使用できます。 この属性がない場合、{Binding} マークアップ拡張を使用できるようにするには、ICustomPropertyProvider インターフェイスと ICustomProperty インターフェイスを実装する必要があります。

既定では、 {Binding} はマークアップ ウィンドウの DataContext にバインドしていることを前提としています。 そのため、ウィンドウの DataContext をバインディング ソース クラスのインスタンス (この場合 HostViewModel 型) に設定します。 次の例は、バインド オブジェクトを宣言するマークアップを示しています。 前の「バインディング ターゲット」セクションで使用したのと同じ Button.Content バインド ターゲットを使用し、 HostViewModel.NextButtonText プロパティにバインドします。

<Window xmlns:viewmodel="using:DataBindingInDepth" ... >
    <Window.DataContext>
        <viewmodel:HostViewModel x:Name="viewModelInDataContext"/>
    </Window.DataContext>
    ...
    <Button Content="{Binding Path=NextButtonText}" ... />
</Window>
// MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    viewModelInDataContext.NextButtonText = "Updated Next button text";
}

Pathに指定された値に注目してください。 ウィンドウの DataContext は、この値を解釈します。この例では、 HostViewModelのインスタンスに設定されています。 パスは、 HostViewModel.NextButtonText プロパティを参照します。 Mode は省略可能です。なぜなら、{Binding} の既定値である一方向バインディングがここで機能するからです。

UI 要素の DataContext の既定値は、その親の継承された値です。 この既定値は、 DataContext 明示的に設定することでオーバーライドできます。この設定は、子によって既定で継承されます。 要素 DataContext 明示的に設定すると、同じソースを使用する複数のバインディングが必要な場合に便利です。

バインド オブジェクトには Source プロパティがあります。既定では、バインディングが宣言されている UI 要素の DataContext が使用されます。 この既定値をオーバーライドするには、バインディングで明示的に SourceRelativeSource、または ElementName を設定します (詳細については 、{Binding} を参照してください)。

DataTemplate 内では、DataContext はテンプレート化されるデータ オブジェクトに自動的に設定されます。 次の例は、ItemTemplate および Title という名前の文字列プロパティを持つ任意の型のコレクションにバインドされた項目コントロールのDescriptionとして使用できます。

<DataTemplate x:Key="SimpleItemTemplate">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{Binding Title}"/>
      <TextBlock Text="{Binding Description"/>
    </StackPanel>
  </DataTemplate>

既定では、 TextBox が フォーカスを失うと、 TextBox.Text への変更が双方向のバインド されたソースに送信されます。 ユーザーのキー操作のたびに変更が送信されるようにするには、マークアップ内のバインドで UpdateSourceTriggerPropertyChanged に設定します。 また、 UpdateSourceTriggerExplicit に設定することで、変更がソースに送信されるタイミングを完全に制御することもできます。 次に、テキスト ボックス (通常 は TextBox.TextChanged) でイベントを処理し、ターゲットで GetBindingExpression を 呼び出して BindingExpression オブジェクトを取得し、最後に BindingExpression.UpdateSource を 呼び出してデータ ソースをプログラムで更新します。

Path プロパティは、入れ子になったプロパティ、添付プロパティ、整数および文字列インデクサーにバインドするためのさまざまな構文オプションをサポートしています。 詳細については、「 プロパティ パスの構文」を参照してください。 文字列インデクサーにバインドすると、 ICustomPropertyProvider を実装しなくても、動的プロパティにバインドする効果が得られます。 ElementName プロパティは、要素間バインディングに役立ちます。 RelativeSource プロパティにはいくつかの用途があります。そのうちの 1 つは、ControlTemplate 内のテンプレート バインドのより強力な代替手段です。 その他の設定については、 {Binding} マークアップ拡張Binding クラスを参照してください。

ソースとターゲットが同じ型でない場合はどうしますか?

ブール型プロパティの値に基づいて UI 要素の表示を制御する場合、または数値の範囲または傾向の関数である色で UI 要素をレンダリングする場合、または文字列を必要とする UI 要素プロパティに日付または時刻の値を表示する場合は、 次に、ある型から別の型に値を変換する必要があります。 適切なソリューションでは、バインディング ソース クラスから適切な型の別のプロパティを公開し、そこで変換ロジックをカプセル化してテストできるようにする場合があります。 ただし、ソースプロパティとターゲットプロパティの数が多い場合や、多数の組み合わせがある場合、そのソリューションは柔軟またはスケーラブルではありません。 その場合は、次の 2 つのオプションがあります。

  • {x:Bind}を使用している場合は、関数に直接バインドしてその変換を行うことができます
  • または、変換を実行するように設計されたオブジェクトである値コンバーターを指定することもできます

値コンバーター

DateTime 値を月を含むstring値に変換する 1 回限りまたは一方向のバインドに適した値コンバーターを次に示します。 このクラスは IValueConverter を実装します

public class DateToStringConverter : IValueConverter
{
    // Define the Convert method to convert a DateTime value to 
    // a month string.
    public object Convert(object value, Type targetType, 
        object parameter, string language)
    {
        // value is the data from the source object.
        DateTime thisDate = (DateTime)value;
        int monthNum = thisDate.Month;
        string month;
        switch (monthNum)
        {
            case 1:
                month = "January";
                break;
            case 2:
                month = "February";
                break;
            default:
                month = "Month not found";
                break;
        }
        // Return the value to pass to the target.
        return month;
    }

    // ConvertBack is not implemented for a OneWay binding.
    public object ConvertBack(object value, Type targetType, 
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

バインド オブジェクト マークアップでその値コンバーターを使用する方法を次に示します。

<UserControl.Resources>
  <local:DateToStringConverter x:Key="Converter1"/>
</UserControl.Resources>
...
<TextBlock Grid.Column="0" 
  Text="{x:Bind ViewModel.Month, Converter={StaticResource Converter1}}"/>
<TextBlock Grid.Column="0" 
  Text="{Binding Month, Converter={StaticResource Converter1}}"/>

バインディング に対して Converter パラメーターが定義されている場合、バインディング エンジンは Convert メソッドと ConvertBack メソッドを呼び出します。 ソースからデータが渡されると、バインディング エンジンは Convert を呼び出し、返されたデータをターゲットに渡します。 ターゲットから (双方向バインディングの場合) データが渡されると、バインディング エンジンは ConvertBack を呼び出し、返されたデータをソースに渡します。

コンバーターには、変換で使用する言語を指定できる ConverterLanguage、および変換ロジックのパラメーターを渡すことができる ConverterParameter という省略可能なパラメーターもあります。 コンバーター パラメーターを使用する例については、「 IValueConverter」を参照してください。

変換にエラーがある場合は、例外をスローしないでください。 代わりに、データ転送を停止する DependencyProperty.UnsetValue を返します。

バインディング ソースを解決できないときに使用する既定値を表示するには、マークアップ内のバインド オブジェクトに FallbackValue プロパティを設定します。 これは、変換と書式設定のエラーを処理するのに役立ちます。 また、異種型のバインドされたコレクション内のすべてのオブジェクトに存在しない可能性があるソース プロパティにバインドする場合にも役立ちます。

文字列以外の値にテキスト コントロールをバインドすると、データ バインディング エンジンによって値が文字列に変換されます。 値が参照型の場合、データ バインディング エンジンは ICustomPropertyProvider.GetStringRepresentation または IStringable.ToString (使用可能な場合) を呼び出して文字列値を取得し、それ以外の場合は Object.ToString を呼び出します。 ただし、バインディング エンジンでは、基底クラスの実装を非表示にする ToString 実装は無視されることに注意してください。 サブクラスの実装では、代わりに基底クラス ToString メソッドをオーバーライドする必要があります。 同様に、ネイティブ言語では、すべてのマネージド オブジェクトが ICustomPropertyProviderIStringable を実装しているように見えます。 ただし、 GetStringRepresentationIStringable.ToString に対するすべての呼び出しは、そのメソッドの Object.ToString またはオーバーライドにルーティングされ、基底クラスの実装を非表示にする新しい ToString 実装にはルーティングされません。

Windows Community Toolkit には、BoolToVisibilityConverter が用意されています。 コンバーターは trueVisible 列挙値にマップし、 falseCollapsed にマップするため、コンバーターを作成せずに Visibility プロパティをブール値にバインドできます。 コンバーターを使用するには、プロジェクトで CommunityToolkit.WinUI.Converters NuGet パッケージを追加する必要があります。

{x:Bind} での関数バインド

{x:Bind} では、バインド パスの最後のステップを関数にすることができます。 この機能は、変換を実行したり、複数のプロパティに依存するバインドを作成したりするために使用します。 詳細については、「 x:Bind の関数」を参照してください。

要素間バインド

1 つの XAML 要素のプロパティを別の XAML 要素のプロパティにバインドできます。 マークアップでのバインドの外観の例を次に示します。

<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />

{x:Bind} を使用したリソース ディクショナリ

{x:Bind} マークアップ拡張はコード生成に依存するため、(生成されたコードを初期化するために) InitializeComponentを呼び出すコンストラクターを含む分離コード ファイルが必要です。 リソース ディクショナリを再利用するには、そのファイル名を参照するのではなく、その型をインスタンス化します ( InitializeComponent が呼び出されるようにします)。 既存のリソース ディクショナリがあり、その中に {x:Bind} を使用する場合の操作の例を次に示します。

<!-- TemplatesResourceDictionary.xaml -->
<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>
// TemplatesResourceDictionary.xaml.cs
using Microsoft.UI.Xaml.Data;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
    }
}
<!-- MainWindow.xaml -->
<Window x:Class="ExampleNamespace.MainWindow"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Window.Resources>
        <ResourceDictionary>
            .... 
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
</Window>

再利用可能なスタイルでの {x:Bind} と {Binding} の混在

前の例では、DataTemplates で {x:Bind} を使用する方法を示しました。 また、 {x:Bind}{Binding} マークアップ拡張の両方を組み合わせた再利用可能なスタイルを作成することもできます。 この組み合わせは、 {x:Bind} を使用してコンパイル時の既知の値に一部のプロパティをバインドし、他のプロパティを {Binding} を使用してランタイム DataContext 値にバインドする場合に便利です。

次の例は、両方のバインド 方法を使用する再利用可能な Button スタイルを作成する方法を示しています。

TemplatesResourceDictionary.xaml

<!-- TemplatesResourceDictionary.xaml -->
<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <!-- DataTemplate using x:Bind -->
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
    
    <!-- Style that mixes x:Bind and Binding -->
    <Style x:Key="CustomButtonStyle" TargetType="Button">
        <Setter Property="Background" Value="{Binding ButtonBackgroundBrush}"/>
        <Setter Property="Foreground" Value="{Binding ButtonForegroundBrush}"/>
        <Setter Property="FontSize" Value="16"/>
        <Setter Property="Margin" Value="4"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="RootBorder"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="4">
                        <StackPanel Orientation="Horizontal" 
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center">
                            <!-- x:Bind to a static property or page-level property -->
                            <Ellipse Width="8" Height="8" 
                                     Fill="{x:Bind DefaultIndicatorBrush}" 
                                     Margin="0,0,8,0"/>
                            <!-- Binding to DataContext -->
                            <ContentPresenter x:Name="ContentPresenter"
                                              Content="{TemplateBinding Content}"
                                              Foreground="{TemplateBinding Foreground}"
                                              FontSize="{TemplateBinding FontSize}"/>
                        </StackPanel>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="PointerOver">
                                    <VisualState.Setters>
                                        <!-- Binding to DataContext for hover color -->
                                        <Setter Target="RootBorder.Background" 
                                                Value="{Binding ButtonHoverBrush}"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <VisualState.Setters>
                                        <!-- x:Bind to a compile-time known resource -->
                                        <Setter Target="RootBorder.Background" 
                                                Value="{x:Bind DefaultPressedBrush}"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

TemplatesResourceDictionary.xaml.cs

// TemplatesResourceDictionary.xaml.cs
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Media;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
        
        // Properties for x:Bind - these are compile-time bound
        public SolidColorBrush DefaultIndicatorBrush { get; } = 
            new SolidColorBrush(Colors.Green);
            
        public SolidColorBrush DefaultPressedBrush { get; } = 
            new SolidColorBrush(Colors.DarkGray);
    }
}

ランタイム値を提供する ViewModel を使用した MainWindow.xaml での使用法:

<!-- MainWindow.xaml -->
<Window x:Class="ExampleNamespace.MainWindow"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <Grid.DataContext>
            <examplenamespace:ButtonThemeViewModel/>
        </Grid.DataContext>
        
        <StackPanel Margin="20">
            <!-- These buttons use the mixed binding style -->
            <Button Content="Save" Style="{StaticResource CustomButtonStyle}"/>
            <Button Content="Cancel" Style="{StaticResource CustomButtonStyle}"/>
        </StackPanel>
    </Grid>
</Window>

ButtonThemeViewModel.cs (ランタイム バインド値を提供する DataContext):

using System.ComponentModel;
using Microsoft.UI;
using Microsoft.UI.Xaml.Media;

namespace ExampleNamespace
{
    public class ButtonThemeViewModel : INotifyPropertyChanged
    {
        private SolidColorBrush _buttonBackgroundBrush = new SolidColorBrush(Colors.LightBlue);
        private SolidColorBrush _buttonForegroundBrush = new SolidColorBrush(Colors.DarkBlue);
        private SolidColorBrush _buttonHoverBrush = new SolidColorBrush(Colors.LightCyan);

        public SolidColorBrush ButtonBackgroundBrush
        {
            get => _buttonBackgroundBrush;
            set
            {
                _buttonBackgroundBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonBackgroundBrush)));
            }
        }

        public SolidColorBrush ButtonForegroundBrush
        {
            get => _buttonForegroundBrush;
            set
            {
                _buttonForegroundBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonForegroundBrush)));
            }
        }

        public SolidColorBrush ButtonHoverBrush
        {
            get => _buttonHoverBrush;
            set
            {
                _buttonHoverBrush = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonHoverBrush)));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

この例では:

  • {Binding} は、DataContext (ButtonBackgroundBrush、ButtonForegroundBrush、ButtonHoverBrush) に依存するプロパティに使用されます。
  • {x:Bind} は、コンパイル時に既知であり、ResourceDictionary 自体に属するプロパティ (DefaultIndicatorBrush、DefaultPressedBrush) に使用されます。
  • スタイルは再利用可能であり、任意のボタンに適用できます
  • ランタイムテーマは、静的要素の {x:Bind} のパフォーマンスの恩恵を受けながら、DataContext を通じて可能です

イベント バインディングと ICommand

{x:Bind} では 、イベント バインドと呼ばれる機能がサポートされています。 この機能を使用すると、バインディングを使用してイベントのハンドラーを指定できます。 この機能は、コードビハインドファイルのメソッドでイベントを処理する方法に加えて、イベントを処理するための追加の選択肢を提供します。 ListViewDoubleTapped クラスにMainWindow イベント ハンドラーがあるとします。

public sealed partial class MainWindow : Window
{
    ...
    public void ListViewDoubleTapped()
    {
        // Handle double-tapped logic
    }
}

次のように、ListView の DoubleTapped イベントを MainWindow のメソッドにバインドできます。

<ListView DoubleTapped="{x:Bind ListViewDoubleTapped}" />

オーバーロードされたメソッドを使用して、この手法でイベントを処理することはできません。 また、イベントを処理するメソッドにパラメーターがある場合は、それらのすべてが、イベントのすべてのパラメーターの型からそれぞれ割り当て可能である必要があります。 この場合、 ListViewDoubleTapped はオーバーロードされず、パラメーターがありません (ただし、2 つの object パラメーターを受け取った場合でも有効です)。

イベント バインド手法は、コマンドの実装と使用に似ています。 コマンドは、 ICommand インターフェイスを実装するオブジェクトを返すプロパティです。 {x:Bind}{Binding} はどちらもコマンドで動作します。 コマンド パターンを複数回実装する必要がないように、DelegateCommand UWP サンプル ("Common" フォルダー) にある ヘルパー クラスを使用できます。

フォルダーまたはファイルのコレクションへのバインド

Windows.Storage 名前空間の API を使用して、パッケージ化された Windows App SDK アプリ内のフォルダーとファイル のデータを取得できます。 ただし、さまざまな GetFilesAsyncGetFoldersAsync、および GetItemsAsync メソッドは、リスト コントロールへのバインドに適した値を返しません。 代わりに、FileInformationFactory クラスの GetVirtualizedFilesVectorGetVirtualizedFoldersVectorおよび GetVirtualizedItemsVector メソッドの戻り値にバインドする必要があります。 StorageDataSource と GetVirtualizedFilesVector UWP サンプルの次のコード例は、一般的な使用パターンを示しています。 アプリ パッケージ マニフェストで picturesLibrary 機能を宣言し、Pictures ライブラリ フォルダーに画像があることを確認してください。

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var library = Windows.Storage.KnownFolders.PicturesLibrary;
    var queryOptions = new Windows.Storage.Search.QueryOptions();
    queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep;
    queryOptions.IndexerOption = Windows.Storage.Search.IndexerOption.UseIndexerWhenAvailable;

    var fileQuery = library.CreateFileQueryWithOptions(queryOptions);

    var fif = new Windows.Storage.BulkAccess.FileInformationFactory(
        fileQuery,
        Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
        190,
        Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale,
        false
        );

    var dataSource = fif.GetVirtualizedFilesVector();
    this.PicturesListView.ItemsSource = dataSource;
}

通常、この方法を使用して、ファイルとフォルダーの情報の読み取り専用ビューを作成します。 たとえば、ユーザーが音楽ビューで曲を評価できるように、ファイルとフォルダーのプロパティへの双方向バインディングを作成できます。 ただし、適切な SavePropertiesAsync メソッド ( MusicProperties.SavePropertiesAsync など) を呼び出すまで、変更は保持されません。 このアクションによって選択のリセットがトリガーされるため、項目がフォーカスを失ったときに変更をコミットする必要があります。

この手法を使用した双方向バインディングは、 Music などのインデックス付きの場所でのみ機能します。 FolderInformation.GetIndexedStateAsync メソッドを呼び出して、場所にインデックスを付けるかどうかを確認できます。

また、仮想化されたベクターは、値を設定する前に、一部の項目の null を返すことができます。 たとえば、仮想化されたベクターにバインドされたリスト コントロールの null 値を使用する前に、を確認するか、代わりに SelectedIndex を使用する必要があります。

キーでグループ化されたデータへのバインド

項目のフラット コレクション ( BookSku クラスで表される書籍など) を取得し、共通プロパティをキー ( BookSku.AuthorName プロパティなど) として使用して項目をグループ化した場合、結果はグループ化されたデータと呼ばれます。 データをグループ化すると、フラット コレクションではなくなります。 グループ化されたデータはグループ オブジェクトのコレクションであり、各グループ オブジェクトには次の情報が含まれます。

  • キー、および
  • そのキーに一致するプロパティを持つ項目のコレクション。

書籍の例をもう一度見ると、著者名で書籍をグループ化した結果、各グループに次の作成者名グループのコレクションが作成されます。

  • キー(作成者名)、および
  • BookSku プロパティがグループのキーと一致するAuthorName オブジェクトのコレクション。

一般に、コレクションを表示するには、項目コントロール (ListViewGridView など) の ItemsSource をコレクションを返すプロパティに直接バインドします。 それが項目の平坦なコレクションである場合、特別なことをする必要はありません。 ただし、グループ オブジェクトのコレクションである場合 (グループ化されたデータにバインドする場合と同様)、項目コントロールとバインド ソースの間に位置する CollectionViewSource と呼ばれる中間オブジェクトのサービスが必要です。 グループ化されたデータを返すプロパティに CollectionViewSource をバインドし、項目コントロールを CollectionViewSourceにバインドします。 CollectionViewSourceの追加の付加価値は、現在の項目を追跡するため、複数の項目を同じCollectionViewSourceにバインドすることで、複数の項目を同期状態に保つことができます。 CollectionViewSource.View プロパティによって返されるオブジェクトの ICollectionView.CurrentItem プロパティを使用して、現在の項目にプログラムでアクセスすることもできます。

CollectionViewSource のグループ化機能をアクティブにするには、IsSourceGroupedtrue に設定します。 ItemsPath プロパティも設定する必要があるかどうかは、グループ オブジェクトの作成方法によって異なります。 グループ オブジェクトを作成するには、"is-a-group" パターンと "has-a-group" パターンの 2 つの方法があります。 "is-a-group" パターンでは、グループ オブジェクトはコレクション型 ( List<T> など) から派生するため、グループ オブジェクトは実際にはそれ自体が項目のグループになります。 このパターンでは、 ItemsPathを設定する必要はありません。 "has-a-group" パターンでは、グループ オブジェクトにはコレクション型の 1 つ以上のプロパティ ( List<T> など) があるため、グループには、プロパティの形式 (または複数のプロパティの形式の項目の複数のグループ) の項目のグループが "ある" ようにします。 このパターンでは、項目のグループを含むプロパティの名前に ItemsPath を設定する必要があります。

次の例は、"has-a-group" パターンを例証しています。 ウィンドウ クラスには、ビュー モデルのインスタンスを返す DataContext という名前のプロパティがあります。 CollectionViewSource は、ビュー モデルのAuthors プロパティ (グループ オブジェクトのコレクションAuthors) にバインドし、グループ化された項目を含むAuthor.BookSkus プロパティであることを指定します。 最後に、 GridViewCollectionViewSourceにバインドされ、グループ内の項目をレンダリングできるように、そのグループ スタイルが定義されています。

<Window.Resources>
    <CollectionViewSource
    x:Name="AuthorHasACollectionOfBookSku"
    Source="{x:Bind ViewModel.Authors}"
    IsSourceGrouped="true"
    ItemsPath="BookSkus"/>
</Window.Resources>
...
<GridView
ItemsSource="{x:Bind AuthorHasACollectionOfBookSku}" ...>
    <GridView.GroupStyle>
        <GroupStyle
            HeaderTemplate="{StaticResource AuthorGroupHeaderTemplateWide}" ... />
    </GridView.GroupStyle>
</GridView>

"is-a-group" パターンは、2 つの方法のいずれかで実装できます。 1 つの方法は、独自のグループ クラスを作成することです。 List<T>からクラスを派生させます (ここで、T は項目の型です)。 たとえば、「 public class Author : List<BookSku> 」のように入力します。 2 つ目の方法は、 LINQ 式を使用して 、BookSku 項目のプロパティ値と同様にグループ オブジェクト (およびグループ クラス) を動的に作成することです。 このアプローチは、項目のフラットなリストのみを保持し、その場でグループ化する方法は、クラウド サービスからデータにアクセスするアプリの一般的な方法です。 作成者やジャンルなどの特別なグループ クラスを必要とせずに、書籍を作成者またはジャンル別にグループ化する柔軟性が得られます。

次の例は、 LINQ を使用した "is-a-group" パターンを示しています。 今回は、ジャンル別に書籍をグループ化し、グループ ヘッダーにジャンル名と共に表示します。 このグループ化は 、グループ Key 値を参照する "Key" プロパティ パスによって示されます。

using System.Linq;
...
private IOrderedEnumerable<IGrouping<string, BookSku>> genres;

public IOrderedEnumerable<IGrouping<string, BookSku>> Genres
{
    get
    {
        if (genres == null)
        {
            genres = from book in bookSkus
                     group book by book.genre into grp
                     orderby grp.Key
                     select grp;
        }
        return genres;
    }
}

データ テンプレートで {x:Bind} を 使用する場合は、 x:DataType 値を設定してバインドされる型を指定する必要があります。 型がジェネリックの場合は、マークアップで表現できないため、代わりにグループ スタイル ヘッダー テンプレートで {Binding} を使用する必要があります。

    <Grid.Resources>
        <CollectionViewSource x:Name="GenreIsACollectionOfBookSku"
        Source="{x:Bind Genres}"
        IsSourceGrouped="true"/>
    </Grid.Resources>
    <GridView ItemsSource="{x:Bind GenreIsACollectionOfBookSku}">
        <GridView.ItemTemplate x:DataType="local:BookTemplate">
            <DataTemplate>
                <TextBlock Text="{x:Bind Title}"/>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Key}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>

SemanticZoom コントロールは、ユーザーがグループ化されたデータを表示および移動するための優れた方法です。 Bookstore2 UWP サンプル アプリは、SemanticZoomの使用方法を示しています。 そのアプリでは、作成者別にグループ化された書籍の一覧 (拡大表示ビュー) を表示したり、縮小して作成者のジャンプ リスト (縮小表示) を表示したりできます。 ジャンプ リストを使用すると、書籍の一覧をスクロールするよりもはるかに高速なナビゲーションが可能になります。 ズームインビューとズームアウトビューは、実際には同じListViewにバインドされたGridViewまたはCollectionViewSourceコントロールです。

SemanticZoom の図

カテゴリ内のサブカテゴリなどの階層データにバインドする場合は、一連の項目コントロールを使用して UI に階層レベルを表示することを選択できます。 1 つの項目コントロールで選択すると、後続の項目コントロールの内容が決まります。 各リストを独自の CollectionViewSource にバインドし、 CollectionViewSource インスタンスをチェーン内でバインドすることで、リストの同期を維持できます。 このセットアップは、マスター/詳細 (またはリスト/詳細) ビューと呼ばれます。 詳細については、「 階層データにバインドし、マスター/詳細ビューを作成する方法」を参照してください。

データ バインディングの問題の診断とデバッグ

バインディング マークアップには、プロパティの名前が含まれています (また、C# の場合は、フィールドやメソッドの場合もあります)。 そのため、プロパティの名前を変更する場合は、それを参照するバインディングも変更する必要があります。 これを忘れた場合は、データ バインディングのバグが作成され、アプリがコンパイルされないか、正しく実行されません。

{x:Bind} と {Binding} によって作成されるバインド オブジェクトは、ほぼ機能的に同等です。 ただし、 {x:Bind} にはバインディング ソースの型情報があり、コンパイル時にソース コードが生成されます。 {x:Bind}では、コードの残りの部分で得られるのと同じ種類の問題検出が得られます。 この検出には、ページの部分クラスとして生成されたソース コードにブレークポイントを設定することで、バインド式のコンパイル時検証とデバッグが含まれます。 これらのクラスは、(C# の場合) objのような名前で、<view name>.g.cs フォルダー内のファイルにあります。 バインドに問題がある場合は、Microsoft Visual Studio デバッガー で [ハンドルされない例外の中断 ] をオンにします。 デバッガーはその時点で実行を中断し、問題が発生したことをデバッグできます。 {x:Bind}によって生成されるコードは、バインディング ソース ノードのグラフの各部分で同じパターンに従います。また、[呼び出し履歴] ウィンドウの情報を使用して、問題の原因となった呼び出しのシーケンスを特定できます。

{Binding} には、バインディング ソースの型情報がありません。 ただし、デバッガーをアタッチしてアプリを実行すると、Visual Studio の [出力 ] ウィンドウと [ XAML バインドエラー ] ウィンドウにバインド エラーが表示されます。 Visual Studio でのバインド エラーのデバッグの詳細については、「 XAML データ バインディング診断」を参照してください。

コードでのバインドの作成

コードで {x:Bind}バインドを作成できないため、このセクションは {Binding} にのみ適用されます。 ただし、{x:Bind} を使用してする場合と同じ利点の一部を実現できます。これにより、依存関係プロパティの変更通知に登録できます。

また、XAML ではなく手続き型コードを使用して、UI 要素をデータに接続することもできます。 これを行うには、新しい Binding オブジェクトを作成し、適切なプロパティを設定してから、 FrameworkElement.SetBinding または BindingOperations.SetBinding を呼び出します。 実行時にバインド プロパティの値を選択したり、複数のコントロール間で 1 つのバインドを共有したりする場合は、プログラムでバインドを作成すると便利です。 ただし、 SetBindingを呼び出した後でバインディング プロパティの値を変更することはできません。

次の例は、コードにバインドを実装する方法を示しています。

<TextBox x:Name="MyTextBox" Text="Text"/>
// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
var textcolor = new MyColors();

// Brush1 is set to be a SolidColorBrush with the value Red.
textcolor.Brush1 = new SolidColorBrush(Colors.Red);

// Set the DataContext of the TextBox MyTextBox.
MyTextBox.DataContext = textcolor;

// Create the binding and associate it with the text box.
var binding = new Binding { Path = new PropertyPath("Brush1") };
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding);

{x:Bind} と {Binding} 機能の比較

特徴 {x:Bind} と {Binding} 注記
Path は既定のプロパティです {x:Bind a.b.c}
-
{Binding a.b.c}
Path プロパティ {x:Bind Path=a.b.c}
-
{Binding Path=a.b.c}
x:Bindでは、Pathは DataContext ではなく、既定で Window にルート化されます。
Indexer {x:Bind Groups[2].Title}
-
{Binding Groups[2].Title}
コレクション内の指定した項目にバインドします。 整数ベースのインデックスのみがサポートされています。
添付プロパティ {x:Bind Button22.(Grid.Row)}
-
{Binding Button22.(Grid.Row)}
添付プロパティはかっこを使用して指定します。 プロパティが XAML 名前空間で宣言されていない場合は、ドキュメントの先頭にあるコード名前空間にマップする必要がある XML 名前空間のプレフィックスを付けます。
キャスティング {x:Bind groups[0].(data:SampleDataGroup.Title)}
-
{Binding}には必要ありません。
キャストはかっこを使用して指定します。 プロパティが XAML 名前空間で宣言されていない場合は、ドキュメントの先頭にあるコード名前空間にマップする必要がある XML 名前空間のプレフィックスを付けます。
コンバータ {x:Bind IsShown, Converter={StaticResource BoolToVisibility}}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}}
コンバーターは、Window、Control、ResourceDictionary、または App.xaml のルートで宣言します。
ConverterParameter、ConverterLanguage {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
-
{Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr}
コンバーターは、Window、Control、ResourceDictionary、または App.xaml のルートで宣言します。
TargetNullValue {x:Bind Name, TargetNullValue=0}
-
{Binding Name, TargetNullValue=0}
バインド式のリーフが null の場合に使用されます。 文字列値には単一引用符を使用します。
FallbackValue {x:Bind Name, FallbackValue='empty'}
-
{Binding Name, FallbackValue='empty'}
バインディングのパスの一部 (リーフを除く) が null の場合に使用されます。
ElementName {x:Bind slider1.Value}
-
{Binding Value, ElementName=slider1}
{x:Bind}フィールドにバインドする場合、Pathは既定で Window にルートされるため、そのフィールドを介して任意の名前付き要素にアクセスできます。
RelativeSource: 自己 <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... />
-
<Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... />
{x:Bind}では、要素に名前を付け、Pathでその名前を使用します。
RelativeSource: テンプレート親 必要ありません。 {x:Bind}
-
{Binding <path>, RelativeSource={RelativeSource TemplatedParent}}
{x:Bind}では、TargetTypeControlTemplateはテンプレートの親へのバインドを示します。 {Binding}の場合、通常のテンプレート バインドは、ほとんどの用途でコントロール テンプレートで使用できます。 ただし、コンバーターまたは双方向バインディングを使用する必要がある場合は、 TemplatedParent を使用します。
情報源 必要ありません。 {x:Bind}
-
<ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/>
{x:Bind}では、名前付き要素を直接使用したり、プロパティまたは静的パスを使用したりできます。
Mode {x:Bind Name, Mode=OneWay}
-
{Binding Name, Mode=TwoWay}
Mode には、 OneTimeOneWay、または TwoWayを指定できます。 {x:Bind} は既定で OneTime に設定され、 {Binding} は既定で OneWay に設定されます。
UpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
-
{Binding UpdateSourceTrigger=PropertyChanged}
UpdateSourceTrigger には、 DefaultLostFocus、または PropertyChangedを指定できます。 {x:Bind} では、 UpdateSourceTrigger=Explicitはサポートされていません。 {x:Bind}では、PropertyChangedを除くすべてのケースでTextBox.Text動作が使用され、LostFocus動作が使用されます。

こちらも参照ください