{x:Bind} マークアップ拡張

{x:Bind} によりアプリでデータ バインディングを使用する方法に関する一般的な情報 (および {x:Bind}{Binding} の全体的な比較) については、「データ バインディングの詳細」をご覧ください。

Windows 10 では、{Binding} に代わり、{x:Bind} マークアップ拡張が新たに提供されています。 {x:Bind} は、{Binding} よりも短い時間および少ないメモリで動作し、より適切なデバッグをサポートしています。

XAML のコンパイル時に、{x:Bind} は、データ ソースのプロパティから値を取得してマークアップで指定されたプロパティに設定するコードに変換されます。 必要な場合、バインディング オブジェクトは、データ ソース プロパティの値の変化を監視し、その変化に基づいて自分自身を更新するように構成できます (Mode="OneWay")。 また、その独自の値の変化をソース プロパティにプッシュするように構成することもできます (Mode="TwoWay")。

{x:Bind}{Binding} によって作成されたバインディング オブジェクトは、ほとんど機能的に同等です。 ただし、{x:Bind} は、コンパイル時に生成される特定用途のコードを実行し、{Binding} は、汎用的なランタイム オブジェクト検査を実行します。 したがって、{x:Bind} バインディング (多くの場合、コンパイル済みバインドと呼ばれます) はパフォーマンスが高く、コンパイル時にバインド式を検証したり、ページの部分クラスとして生成されたコード ファイル内にブレークポイントを設定し、デバッグを行ったりできます。 これらのファイルは obj フォルダー内にあり、<view name>.g.cs (C# の場合) などの名前が付けられています。

ヒント

{Binding} の既定のモードは OneWay ですが、{x:Bind} の既定のモードは OneTime です。 これはパフォーマンス上の理由から選ばれました。OneWay を使うと、接続して変更検出を処理するために生成されるコードが多くなるためです。 OneWay または TwoWay バインディングを使うようにモードを明示的に指定することができます。 x:DefaultBindMode を使って、マークアップ ツリーの特定のセグメントで {x:Bind} の既定のモードを変更することもできます。 指定されたモードは、バインドの一部として明示的にモードが指定されている場合を除いて、対象の要素とその子に対するすべての {x:Bind} 式に適用されます。

{x:Bind} の使い方を示すサンプル アプリ

XAML 属性の使用方法

<object property="{x:Bind}" .../>
-or-
<object property="{x:Bind propertyPath}" .../>
-or-
<object property="{x:Bind bindingProperties}" .../>
-or-
<object property="{x:Bind propertyPath, bindingProperties}" .../>
-or-
<object property="{x:Bind pathToFunction.functionName(functionParameter1, functionParameter2, ...), bindingProperties}" .../>
項目 説明
propertyPath バインドのプロパティ パスを指定する文字列。 詳しくは、以下の「プロパティ パス」をご覧ください。
bindingProperties
propName=value[, propName=value]* 名前と値のペアの構文を使って指定する、1 つ以上のバインド プロパティ。
propName Binding オブジェクトで設定するプロパティの文字列名。 たとえば、"Converter" です。
value プロパティに設定する値。 引数の構文は、設定されているプロパティによって異なります。 値がそれ自体マークアップ拡張である propName=value の使用例を示します: Converter={StaticResource myConverterClass}。 詳しくは、以下の「{x:Bind} で設定できるプロパティ」をご覧ください。

<Page x:Class="QuizGame.View.HostView" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

この例の XAML では、{x:Bind}ListView.ItemTemplate プロパティと共に使用されています。 x:DataType 値の宣言に注意してください。

  <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>

[プロパティのパス]

PropertyPath{x:Bind} 式の Path です。 Path は、バインド先のプロパティ、サブプロパティ、フィールド、またはメソッドの値 (ソース) を指定するプロパティ パスです。 Path プロパティの名前は、{x:Bind Path=...} のように明示的に指定することができます。 または、{x:Bind ...} のように省略することもできます。

プロパティのパスの解決

{x:Bind} は、既定のソースとして DataContext を使わず、代わりにページまたはユーザー コントロール自体を使います。 したがって、ページまたはユーザー コントロールのコード ビハインドでプロパティ、フィールド、およびメソッドが検索されます。 通常、ビュー モデルを {x:Bind} に公開するには、ページまたはユーザー コントロールのコード ビハインドに新しいフィールドまたはプロパティを追加する必要があります。 プロパティ パスのステップは、ドット (.) で区切ります。複数の区切り記号を指定することで、連続するサブプロパティを走査できます。 バインドされているオブジェクトを実装するために使用するプログラミング言語に関係なく、ドット区切り記号を使います。

たとえば、あるページで、Text="{x:Bind Employee.FirstName}" を指定すると、そのページの Employee メンバーが検索され、次に、Employee が返したオブジェクトの FirstName メンバーが検索されます。 従業員の扶養家族を含むプロパティに項目コントロールをバインドする場合、プロパティ パスは "Employee.Dependents" となり、"Dependents" の項目の表示には項目コントロールの項目テンプレートが使われます。

C++/CX の場合、{x:Bind} はページまたはデータ モデルのプライベート フィールドおよびプロパティにバインドできません。バインドできるようにするには、パブリック プロパティが必要です。 バインド用のサーフェス領域を CX クラス/インターフェイスとして公開し、関連するメタデータを取得できるようにする必要があります。 [Bindable] 属性は必要ありません。

x:Bind では、ElementName=xxx をバインド式の一部として使用する必要はありません。 代わりに、要素の名前をバインディングのパスの先頭部分として使用できます。これは、名前付き要素が、ルート バインディング ソースを表すページまたはユーザー コントロール内のフィールドになるためです。

コレクション

データ ソースがコレクションである場合、プロパティ パスには、位置またはインデックスによりコレクション内の項目を指定できます。 たとえば "Teams[0].Players" では、"0" をリテラル "[]" で囲むことで、インデックス 0 で始まるコレクション内の最初の項目を要求します。

インデクサーを使用するには、インデックスを作成するプロパティの型に IList<T> または IVector<T> を実装する必要があります。 (IReadOnlyList<T> および IVectorView<T> はインデクサー構文をサポートしていません。インデックス付きプロパティの型が INotifyCollectionChanged または IObservableVector をサポートしていて、バインディングが OneWay または TwoWay である場合、それらのインターフェイスで変更通知を登録してリッスンします。 変更検出ロジックは、特定のインデックス付きの値に影響を与えない場合でも、すべてのコレクションの変更に基づいて更新されます。 これは、リッスンしているロジックがコレクションのすべてのインスタンス間で共通であるためです。

データ ソースがディクショナリまたはマップである場合、プロパティ パスには、文字列名によりコレクション内の項目を指定できます。 たとえば、<TextBlock Text="{x:Bind Players['John Smith']}" /> と指定すると、ディクショナリで "John Smith" という名前の項目が検索されます。 名前は引用符で囲む必要があり、単一引用符と二重引用符のどちらでも使用できます。 文字列で引用符をエスケープするにはハット (^) を使用できます。 XAML 属性に使用されるものから代替引用符を使用するのが最も簡単です。 (IReadOnlyDictionary<T> と IMapView<T> はインデクサー構文には対応していないのでご注意ください。)

文字列インデクサーを使用するには、インデックスを作成するプロパティの型に IDictionary<文字列 T> または IMap<文字列 T> を実装する必要があります。 インデックス付きプロパティの型が IObservableMap をサポートしており、バインディングが OneWay または TwoWay の場合、そのプロパティは登録され、それらのインターフェイスで変更通知をリッスンします。 変更検出ロジックは、特定のインデックス付きの値に影響を与えない場合でも、すべてのコレクションの変更に基づいて更新されます。 これは、リッスンしているロジックがコレクションのすべてのインスタンス間で共通であるためです。

添付プロパティ

添付プロパティにバインドするには、クラスおよびプロパティ名をドットの後のかっこ内に含める必要があります。 たとえば、Text="{x:Bind Button22.(Grid.Row)}" などです。 プロパティが Xaml 名前空間で宣言されていない場合は、そのプロパティの前に xml 名前空間を付ける必要があります。これはドキュメントの先頭でコード名前空間にマップする必要があります。

キャスト

コンパイル済みのバインドは、厳密に型指定され、パスの各ステップの型を解決します。 返される型にメンバーがない場合は、コンパイル時に失敗します。 キャストを指定して、オブジェクトの実際の型をバインディングに通知することができます。

次の場合、obj は型オブジェクトのプロパティですが、テキスト ボックスを含んでいます。したがって、Text="{x:Bind ((TextBox)obj).Text}" または Text="{x:Bind obj.(TextBox.Text)}" を使用できます。

Text="{x:Bind ((data:SampleDataGroup)groups3[0]).Title}"groups3 フィールドは、オブジェクトのディクショナリです。したがって、data:SampleDataGroup にキャストする必要があります。 既定の XAML 名前空間の一部ではないコード名前空間にオブジェクトの型をマップするための xml data: 名前空間のプレフィックスの使用法に注意してください。

注: C# スタイルのキャスト構文は添付プロパティ構文より柔軟であり、今後はこの構文が推奨されます。

パスを使用しないキャスト

ネイティブ バインド パーサーには、this を関数パラメーターとして表すキーワードはありませんが、関数パラメーターとして使用できるパスを使用しないキャスト (例: {x:Bind (x:String)}) に対応しています。 したがって、{x:Bind MethodName(this)} と概念的に同等なことを実行するのに、{x:Bind MethodName((namespace:TypeOfThis))} は有効な方法です。

例:

Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}"

<Page
    x:Class="AppSample.MainPage"
    ...
    xmlns:local="using:AppSample">

    <Grid>
        <ListView ItemsSource="{x:Bind Songs}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:SongItem">
                    <TextBlock
                        Margin="12"
                        FontSize="40"
                        Text="{x:Bind local:MainPage.GenerateSongTitle((local:SongItem))}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>
namespace AppSample
{
    public class SongItem
    {
        public string TrackName { get; private set; }
        public string ArtistName { get; private set; }

        public SongItem(string trackName, string artistName)
        {
            ArtistName = artistName;
            TrackName = trackName;
        }
    }

    public sealed partial class MainPage : Page
    {
        public List<SongItem> Songs { get; }
        public MainPage()
        {
            Songs = new List<SongItem>()
            {
                new SongItem("Track 1", "Artist 1"),
                new SongItem("Track 2", "Artist 2"),
                new SongItem("Track 3", "Artist 3")
            };

            this.InitializeComponent();
        }

        public static string GenerateSongTitle(SongItem song)
        {
            return $"{song.TrackName} - {song.ArtistName}";
        }
    }
}

バインディング パス内の関数

Windows 10 バージョン 1607 以降、 {x:Bind} はバインド パスのリーフ ステップとしての関数の使用をサポートします。 これはデータバインディングにとって強力な機能であり、マークアップにおいて複数のシナリオを可能にします。 詳しくは、関数バインドに関する記事をご覧ください。

イベント バインディング

イベント バインディングは、コンパイル済みのバインドの固有の機能です。 これにより、バインディングを使用するイベントのハンドラーを指定でき、それをコード ビハインドのメソッドにする必要はありません。 たとえば、Click="{x:Bind rootFrame.GoForward}" などです。

イベントの場合、対象のメソッドをオーバーロードしてはならず、以下の条件も満たしている必要があります。

  • イベントのシグネチャが一致している。
  • または、パラメーターを持たない。
  • または、イベント パラメーターの型から割り当て可能な型のパラメーターを同じ数だけ持つ。

生成されたコード ビハインドでは、コンパイル済みのバインドは、イベントを処理してモデルのメソッドにルーティングします。また、イベントが発生すると、バインド式のパスを評価します。 つまり、プロパティ バインディングとは異なり、モデルの変更を追跡しません。

プロパティ パスの文字列構文について詳しくは、ここで説明した {x:Bind} に対する違いに注意して、「プロパティ パス構文」をご覧ください。

{x:Bind} で設定できるプロパティ

{x:Bind} は、bindingProperties プレースホルダー構文で示されます。これは、マークアップ拡張で設定可能な読み取り/書き込みプロパティが複数あるためです。 プロパティは、propName=value ペアをコンマで区切ることにより、任意の順序で設定できます。 バインド式に改行を含めることはできないことに注意してください。 プロパティによっては、型変換をサポートしていない型が必要なものがあります。そのため、これらのプロパティでは、{x:Bind} 内で入れ子にされた独自のマークアップ拡張が必要です。

これらのプロパティは、Binding クラスのプロパティとほぼ同じように機能します。

プロパティ 説明
パス 上記の「プロパティ パス」をご覧ください。
Converter バインド エンジンによって呼び出されるコンバーター オブジェクトを指定します。 コンバーターは XAML で設定できますが、リソース ディクショナリ内のオブジェクトへの {StaticResource} マークアップ拡張 参照で割り当てたオブジェクト インスタンスを参照する場合に限られます。
ConverterLanguage コンバーターで使うカルチャを指定します (ConverterLanguage を設定する場合は Converter も設定する必要があります)。カルチャは、標準ベースの識別子として設定できます。 詳しくは、「ConverterLanguage」をご覧ください。
ConverterParameter コンバーター ロジックで使うことができるコンバーター パラメーターを指定します (ConverterParameter を設定する場合は Converter も設定する必要があります)。 ほとんどのコンバーターは、渡された値から変換に必要なすべての情報を取得するという単純なロジックを使っており、ConverterParameter 値を必要としません。 ConverterParameter パラメーターは、ConverterParameter で渡された値を利用する複数のロジックを持つ、ある程度高度なコンバーターを実装するために存在します。 また、文字列以外の値を使うコンバーターも作成できますが、一般的ではありません。詳しくは、「ConverterParameter」の「注釈」をご覧ください。
FallbackValue ソースまたはパスを解決できない場合に表示する値を指定します。
モード "OneTime"、"OneWay"、"TwoWay" のいずれかの文字列として、バインド モードを指定します。 既定は "OneTime" です。 これは、{Binding} の既定値 (ほとんどの場合は "OneWay") とは異なる点に注意してください。
TargetNullValue ソース値が解決されるが、明示的に null である場合に表示する値を設定します。
BindBack 双方向バインディングの逆方向に使う関数を指定します。
UpdateSourceTrigger コントロールから双方向バインディングのモデルに変更を戻すタイミングを指定します。 TextBox.Text を除くすべてのプロパティの既定値は PropertyChanged です (TextBox.Text は LostFocus)。

注意

マークアップを {Binding} から {x:Bind} に変換する場合は、Mode プロパティの既定値の違いに注意してください。 x:DefaultBindMode X:bind のマークアップ ツリーの特定のセグメントの既定のモードを変更するために使用できます。 選択されたモードは、バインドの一部として明示的にモードが指定されている場合を除いて、対象の要素とその子に対するすべての x:Bind 式に適用されます。 OneTime は、OneWay より重要です。OneWay を使うと、接続して変更検出を処理するために生成されるコードが多くなるためです。

注釈

{x:Bind} は、その利点を得るために、生成されたコードを使用するので、コンパイル時に型情報が必要です。 つまり、型が事前にわかっていない場合は、プロパティにバインドできません。 このため、{x:Bind} は、型が Object で、実行時に変更されることもある DataContext プロパティと共に使用することはできません。

{x:Bind} をデータ テンプレートと共に使用するときは、「」のセクションに示すように、x:DataType 値を設定し、バインド先の型を指定する必要があります。 型をインターフェイスまたは基底クラス型に設定することもでき、完全な式を指定するために必要な場合は、キャストを使用できます。

コンパイル済みバインドは、コード生成によって異なります。 そのため、リソース ディクショナリで {x:Bind} を使う場合、リソース ディクショナリにはコード ビハインド クラスが必要です。 コード例については、「リソース ディクショナリと {x:Bind}」をご覧ください。

コンパイル済みバインドを含むページやユーザー コントロールでは、生成されたコードに "Bindings" プロパティが含まれます。 これには次のメソッドが含まれます。

  • Update() - すべてのコンパイル済みバインドの値を更新します。 すべての 1 方向/双方向バインディングには、変更を検出するためにフックされたリスナーがあります。
  • Initialize() - バインディングがまだ初期化されていない場合、Update() を呼び出してバインディングを初期化します。
  • StopTracking() - 1 方向と双方向のバインディングに作成されたすべてのリスナーをフック解除します。 Update() メソッドを使って再初期化できます。

注意

Windows 10、バージョン1607 以降では、XAML フレームワークにブール値と Visibility 値のコンバーターが組み込まれています。 コンバーターは、Visible 列挙値に対して true を、Collapsed に対して false をマッピングします。これにより、コンバーターを作成せずに Visibility プロパティをブール値にバインドできます。 これは、関数バインドの機能ではないことに注意してください。プロパティのバインドにすぎません。 組み込みのコンバーターを使用するには、アプリの最小のターゲット SDK バージョンが 14393 以降である必要があります。 アプリがそれよりも前のバージョンの Windows 10 をターゲットとしている場合は使うことができません。 ターゲット バージョンについて詳しくは、「バージョン アダプティブ コード」をご覧ください。

ヒント:PathConverterParameter のように、値に 1 つの中かっこを指定する必要がある場合は、\{ のように円記号 (バックスラッシュ) を中かっこの前に付けます。 別の方法として、エスケープする必要がある中かっこを含む文字列全体を ConverterParameter='{Mix}' のように別の種類の引用符で囲みます。

ConverterConverterLanguageConverterLanguage はいずれも、バインド ソースの値または型を、バインディング ターゲットのプロパティと互換性のある型または値に変換するシナリオに関係があります。 例や詳しい情報については、「データ バインディングの詳細」の「データの変換」をご覧ください。

{x:Bind} は、マークアップ拡張のみです。このようなバインディングをプログラムで作成したり操作したりする方法はありません。 マークアップ拡張について詳しくは、「XAML の概要」をご覧ください。