VB のたまご

作成日: 2017/03/19, 更新日: 2017/03/19



DataContext プロパティについて

    イメージ
  •  ここでは、データバインドについて学習していきます。データをバインドする技術の事ですね。どこの部分かと言うと View ⇔ ViewModel を疎結合してくれる部分の技術です。 実際に結合する仕事をしているのが、DataContext プロパティです。このプロパティにデータクラスのインスタンスをセットすることで、 データが各コントロールの必要とされているところに表示されます。

  • スポンサーリンク


  •  とりあえずどういう風に動くのか見てみましょう。 以下サンプルです。「DataContextWindow1」という画面で作成していますが、「MainWindow」に書いても構いません。 ※標準の WPF アプリケーションで作成しています。

  •  以下は、表示するデータクラス、画面、コードビハインドです。

  • Public Class Class1
    
        Public Property MyName As String = "taro1"
        Public MyName2 As String = "taro1"
        Public Property Age As Integer = -1
    
        Public Sub New()
    
            ' コメントアウトを外すと・・・
            'Me.MyName = "taro2"
            'Me.Age = 23
    
        End Sub
    
    End Class
    

    <Window x:Class="DataContextWindow1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:w02_DataBinding1"
            mc:Ignorable="d"
            Title="DataContextWindow1" Height="300" Width="300">
    
        <StackPanel>
    
            <Button Content="{Binding MyName}" />
            <Button Content="{Binding MyName2}" />
    
        </StackPanel>
        
    </Window>
    

    Public Class DataContextWindow1
    
        Public Sub New()
    
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            Me.DataContext = New Class1
    
        End Sub
    
    End Class
    

  •  これを実行すると、1つ目のボタンに「taro1」と書かれた画面が表示されます。2つ目のボタンには何も文字列が表示されていません。 つまりバインドしたデータを表示したい場合は、プロパティである必要があります。MyName2 はフィールドなので、表示されなかったんですね。

  •  それでは、Class1.vb のコンストラクタに記載したコメントアウト部分を外して実行してみましょう。 今度はボタンには「taro2」と表示されました。まあ想像通りだと思います。

  • スポンサーリンク


  •  ところで、DataContext プロパティへのセットは、コード上だけではなく Xaml 上からもセットすることができます。

  • <Window x:Class="DataContextWindow2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:w02_DataBinding1"
            mc:Ignorable="d"
            Title="DataContextWindow2" Height="300" Width="300">
    
        <Window.DataContext>
            <local:Class1 />
        </Window.DataContext>
        
        <StackPanel>
    
            <Button Content="{Binding MyName}" />
    
        </StackPanel>
    
    </Window>
    

    Public Class DataContextWindow2
    
    End Class
    

  •  これを実行すると、コードビハインドには何も書いていないまま、ボタンに「taro2」と書かれていることが分かります。 それでは両方にセットしてみるとどうなるでしょうか。

  • <Window x:Class="DataContextWindow3"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:w02_DataBinding1"
            mc:Ignorable="d"
            Title="DataContextWindow3" Height="300" Width="300">
    
        <Window.DataContext>
            <local:Class1 MyName="hanako" Age="32" />
        </Window.DataContext>
    
        <StackPanel>
    
            <Button Content="{Binding MyName}" />
            <Button Content="{Binding Age}" />
    
        </StackPanel>
    
    </Window>
    

    Public Class DataContextWindow3
    
        Public Sub New()
    
            ' この呼び出しはデザイナーで必要です。
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            Me.DataContext = New Class1 With {.MyName = "himawari"}
    
        End Sub
    
    End Class
    

  •  実行しますと、コード上でセットした値が表示されています。コード上の設定が優先されるんですね。 試しにコード上の命令をコメントアウトすると、Xaml 上でセットした情報がボタンに表示されているはずです。 Xaml 上での設定がしっかり生きていることが分かると思います。

  • イメージ
  •  バインドデータを表示する場合、コントロールは DataContext プロパティを参照します。 ここで言うと最初は 自分自身(Button)です。未セットなので、親の DataContext プロパティを確認します。 ここでは StackPanel ですね。StackPanel.DataContext プロパティも未セットなので、その親となる Window.DataContext プロパティを確認します。 ここには Class1 のインスタンスがセットされており、MyName プロパティや Age プロパティがあるので、ここから値を引っ張ってきて表示します。

  •  ということで、DataContext プロパティは Window 専用のプロパティではありません。 DataContext プロパティはほとんどのコントロールが持っているプロパティです。

  •  今度は、複数の DataContext プロパティに、複数のデータクラスをセットしてみます。

  •  2つ目のデータ、画面の順です。

  • Public Class Class2
    
        Public Property MyName As String = String.Empty
        Public Property Age As Integer = -1
    
        Public Sub New()
    
            Me.MyName = "jiro"
            Me.Age = 28
    
        End Sub
    
    End Class
    

    <Window x:Class="DataContextWindow4"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:w02_DataBinding1"
            mc:Ignorable="d"
            Title="DataContextWindow4" Height="300" Width="300">
    
        <Window.Resources>
            <local:Class1 x:Key="Class1Instance" />
            <local:Class2 x:Key="Class2Instance" />
        </Window.Resources>
    
        <Window.DataContext>
            <StaticResource ResourceKey="Class1Instance" />
        </Window.DataContext>
        
        <StackPanel>
    
            <Button Content="{Binding MyName}" />
            <Button Content="{Binding MyName}" DataContext="{StaticResource Class2Instance}" />
    
        </StackPanel>
        
    </Window>
    

    Public Class DataContextWindow4
    
    End Class
    

  •  あらかじめ、リソースに、Class1 と Class2 の2つのインスタンスを用意しておきます。 リソースにある「Class1」の参照を Window.DataContext プロパティにセットします。

  •  これを実行すると、1つ目のボタンには「taro2」と表示され、2つ目のボタンには「jiro」と表示されます。 つまり、1つ目のボタンの「MyName」は親にセットされた「Class1」を参照していて、 2つ目のボタンの「MyName」は、リソースにある「Class2」の参照を 直接 Button の DataContext プロパティにセットしているからだということが分かります。