バインディング宣言の概要 (WPF .NET)

通常、開発者は、データをバインドする UI 要素の XAML マークアップで直接バインディングを宣言します。 ただし、コードでバインディングを宣言することもできます。 この記事では、XAML とコードの両方でバインディングを宣言する方法について説明します。

前提条件

この記事を読む前に、マークアップ拡張機能の概念と使用方法について理解している必要があります。 マークアップ拡張機能の詳細については、 「マークアップ拡張機能と WPF XAML」を参照してください。

この記事では、データ バインディングの概念については説明しません。 データ バインディングの概念の詳細については、「データ バインディングの概要」を参照してください。

XAML でのバインディングの宣言

Binding はマークアップ拡張機能です。 バインディング拡張機能を使用してバインディングを宣言するとき、この宣言は、Binding キーワードに続く一連の句で構成され、コンマ (,) で区切られます。 バインディング宣言内の句の順序は任意で、多数の組み合わせが可能です。 句は名前=のペアで、"名前" は Binding プロパティの名前、"" はこのプロパティに設定する値です。

マークアップでバインディング宣言文字列を作成する場合、この文字列はターゲット オブジェクトの特定の依存関係プロパティにアタッチする必要があります。 次の例では、バインディング拡張機能を使用して TextBox.Text プロパティをバインドし、Source プロパティと Path プロパティを指定する方法を示します。

<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=Name}"/>

Binding クラスのプロパティのほとんどをこの方法で指定できます。 バインディング拡張機能およびバインディング拡張機能を使用して設定できない Binding プロパティの一覧については、「バインドのマークアップ拡張機能 (.NET Framework)」の概要を参照してください。

オブジェクト要素構文

オブジェクト要素構文は、バインディング宣言を作成する代替の方法です。 ほとんどの場合は、マークアップ拡張機能の使用とオブジェクト要素構文の使用のどちらにも特別な利点はありません。 ただし、マークアップ拡張機能でシナリオがサポートされない場合は (プロパティ値が文字列タイプではなく、このタイプの変換が存在しない場合)、オブジェクト要素構文を使用する必要があります。

前のセクションでは、XAML 拡張機能とバインドする方法を説明しました。 次の例は、同じバインディングを実行する方法を示していますが、オブジェクト要素の構文を使用しています。

<TextBlock>
    <TextBlock.Text>
        <Binding Source="{StaticResource myDataSource}" Path="Name"/>
    </TextBlock.Text>
</TextBlock>

別の用語の詳細については、「XAML Syntax の詳細 (.NET Framework)」を参照してください。

MultiBinding と PriorityBinding

MultiBindingPriorityBinding では、XAML 拡張構文はサポートされていません。 したがって、XAML で MultiBinding または PriorityBinding を宣言する場合は、オブジェクト要素構文を使用する必要があります。

コードでバインディングを作成する

バインディングを指定するもう 1 つの方法は、コード内の Binding オブジェクトにプロパティを直接設定してから、バインディングをプロパティに割り当てる方法です。 Binding オブジェクトをコードで作成する方法の例を次に示します。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // Make a new data source object
    var personDetails = new Person()
    {
        Name = "John",
        Birthdate = DateTime.Parse("2001-02-03")
    };

    // New binding object using the path of 'Name' for whatever source object is used
    var nameBindingObject = new Binding("Name");

    // Configure the binding
    nameBindingObject.Mode = BindingMode.OneWay;
    nameBindingObject.Source = personDetails;
    nameBindingObject.Converter = NameConverter.Instance;
    nameBindingObject.ConverterCulture = new CultureInfo("en-US");

    // Set the binding to a target object. The TextBlock.Name property on the NameBlock UI element
    BindingOperations.SetBinding(NameBlock, TextBlock.TextProperty, nameBindingObject);
}
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)

    ' Make a new data source object
    Dim personDetails As New Person() With {
        .Name = "John",
        .Birthdate = Date.Parse("2001-02-03")
    }

    ' New binding object using the path of 'Name' for whatever source object is used
    Dim nameBindingObject As New Binding("Name")

    ' Configure the binding
    nameBindingObject.Mode = BindingMode.OneWay
    nameBindingObject.Source = personDetails
    nameBindingObject.Converter = NameConverter.Instance
    nameBindingObject.ConverterCulture = New CultureInfo("en-US")

    ' Set the binding to a target object. The TextBlock.Name property on the NameBlock UI element
    BindingOperations.SetBinding(NameBlock, TextBlock.TextProperty, nameBindingObject)

End Sub

前のコードでは、バインディングに次の設定を行いました。

  • データ ソース オブジェクトのプロパティのパス。
  • バインディングのモード。
  • データ ソース (この場合は、人物を表す単純なオブジェクト インスタンス)。
  • ターゲット プロパティに割り当てる前に、データ ソース オブジェクトからの値を処理する省略可能なコンバーター。

バインディングしているオブジェクトが FrameworkElement または FrameworkContentElement の場合、BindingOperations.SetBinding を使用する代わりに、オブジェクトで SetBinding メソッドを直接呼び出すことができます。 例については、「方法 : コードでバインディングを作成する」を参照してください。

前の例では、単純なデータ オブジェクト型 Person を使用しています。 そのオブジェクトのコードを次に示します。

class Person
{
    public string Name { get; set; }
    public DateTime Birthdate { get; set; }
}
Public Class Person

    Public Property Name As String
    Public Property Birthdate As DateTime
    
End Class

バインディング パス構文

Path プロパティを使用して、バインドするソース値を指定します。

  • 最も簡単なケースでは、Path プロパティの値は、バインディングに使用するソース オブジェクトのプロパティの名前です (Path=PropertyName など)。

  • プロパティのサブプロパティは、C# と同様の構文で指定できます。 たとえば、句 Path=ShoppingCart.Order は、バインディングをオブジェクトのサブプロパティ Order またはプロパティ ShoppingCart に設定します。

  • 添付プロパティにバインドするには、添付プロパティをかっこで囲みます。 たとえば、添付プロパティ DockPanel.Dock にバインドする構文は Path=(DockPanel.Dock) です。

  • プロパティのインデクサーは、インデクサーが適用されているプロパティ名の後ろの角かっこ内に指定できます。 たとえば、句 Path=ShoppingCart[0] は、プロパティの内部インデックスがリテラル文字列「0」を処理する方法に対応するインデックスへのバインディングを設定します。 入れ子になったインデクサーもサポートします。

  • Path 句ではインデクサーとサブプロパティを混在させることができます。例: Path=ShoppingCart.ShippingInfo[MailingAddress,Street].

  • インデクサー内。 コンマ (,) で区切って複数のインデクサー パラメーターを指定できます。 各パラメーターの型は、かっこで指定できます。 たとえば、Path="[(sys:Int32)42,(sys:Int32)24]" などと指定できます。この場合、sysSystem 名前空間にマップされます。

  • ソースがコレクション ビューの場合は、現在の項目をスラッシュ (/) で指定できます。 たとえば、句 Path=/ では、ビューの現在の項目に対するバインディングが設定されます。 ソースがコレクションの場合、この構文では、既定のコレクション ビューの現在の項目を指定します。

  • プロパティ名とスラッシュを組み合わせて、コレクションであるプロパティを走査することができます。 たとえば、Path=/Offices/ManagerName では、それもコレクションである Offices プロパティが含まれるソース コレクションの現在の項目が指定されます。 現在の項目は、ManagerName プロパティを含むオブジェクトです。

  • 必要に応じて、ピリオド (.) のパスを使用して、現在のソースにバインドできます。 たとえば、Text="{Binding}" は、Text="{Binding Path=.}" と同じです。

エスケープのしくみ

  • インデクサー ([ ]) 内では、キャレット文字 (^) は次の文字をエスケープします。

  • XAML で Path を設定した場合、XML 言語定義で特別な意味を持つ特定の文字も (XML エンティティを使用して) エスケープする必要があります。

    • 文字 "&" をエスケープするには、&amp; を使用します。

    • 終了タグ ">" をエスケープするには、&gt; を使用します。

  • さらに、マークアップ拡張構文を使用して属性のバインディング全体を記述する場合、WPF マークアップ拡張機能パーサーで特別な意味を持つ文字を (円記号 \ を使用して) エスケープする必要があります。

    • バックスラッシュ (\) は、それ自体がエスケープ文字です。

    • 等号 (=) は、プロパティ名とプロパティ値を区切ります。

    • コンマ (,) は、複数のプロパティを区切ります。

    • 右中かっこ (}) は、マークアップ拡張機能の終了を示します。

バインドの方向

バインディングの方向を指定するには、Binding.Mode プロパティを使用します。 次のモードは、バインディングの更新に使用できるオプションです。

バインディング モード Description
BindingMode.TwoWay ターゲットのプロパティまたはソースのプロパティのいずれかが変更されるたびに、ターゲットのプロパティまたはソースのプロパティを更新します。
BindingMode.OneWay ソースのプロパティが変更された場合にのみ、ターゲットのプロパティを更新します。
BindingMode.OneTime アプリケーションが開始されたとき、または DataContext が変更された場合にのみ、ターゲットのプロパティを更新します。
BindingMode.OneWayToSource ターゲット プロパティが変更されると、ソース プロパティを更新します。
BindingMode.Default ターゲットのプロパティの既定の Mode 値が使用されます。

詳細については、BindingMode 列挙型のページをご覧ください。

Mode プロパティを設定する方法を次の例に示します。

<TextBlock Name="IncomeText" Text="{Binding Path=TotalIncome, Mode=OneTime}" />

ソースの変更を検出するには (OneWay および TwoWay バインディングに適用)、ソースに INotifyPropertyChanged などの適切なプロパティ変更通知メカニズムを実装する必要があります。 詳細については、「変更通知の提供」を参照してください。

TwoWay または OneWayToSource バインディングの場合は、UpdateSourceTrigger プロパティを設定することによって、ソースの更新のタイミングを制御できます。 詳細については、「UpdateSourceTrigger」を参照してください。

既定の動作

既定の動作は、宣言で指定されていない場合には次のとおりです。

  • バインディング ソースの値とバインディング ターゲットの値の型変換を実行しようとする既定のコンバーターが作成されます。 変換を実行できない場合、既定のコンバーターは null を返します。

  • ConverterCulture を設定しない場合、バインディング エンジンではバインディング ターゲット オブジェクトの Language プロパティが使用されます。 XAML では、既定で en-US になるか、または明示的に設定されている場合にはページのルート要素 (または任意の要素) から値を継承します。

  • バインディングに既にデータ コンテキスト (たとえば、親要素から継承したデータ コンテキスト) があり、そのコンテキストによって返される項目またはコレクションが、さらなるパスの変更を必要とせずにバインディングに対して適切である限り、バインディング宣言に句がまったくなくてもかまいません: {Binding}。 これは、多くの場合、データのスタイルに対してバインディングを指定する方法で、バインディングはコレクションに基づいて動作します。 詳細については、「バインディング ソースとしてオブジェクト全体を使用する」を参照してください。

  • 既定の Mode は、バインドされている依存関係プロパティによって一方向と双方向で異なります。 常にバインディング モードを明示的に宣言し、バインディングに目的の動作があることを確認できます。 一般に、ユーザーが編集できる TextBox.TextRangeBase.Value などのコントロール プロパティは既定で双方向のバインディングですが、それ以外のほとんどのプロパティは既定で一方向のバインドになります。

  • 既定の UpdateSourceTrigger 値は、バインドされている依存関係プロパティによっても PropertyChangedLostFocus で異なります。 ほとんどの依存関係プロパティの既定値は PropertyChanged です。ただし、TextBox.Text プロパティの既定値は LostFocus です。

関連項目