mikeo_410


WPFのバインディング

1.XAMLで記述したコントロール間でのバインディング

  キー入力用の TextBox と表示用の TextBlock の2つのコントロールを配置します。
  TextBoxに1文字入力するごとに、TextBlockにも同じ内容が表示されます。

  1. <TextBox Name="textBox1"  Grid.Column="0" Grid.Row="0" />
  2. <TextBlock Grid.Column="1" Grid.Row="0">
  3.     <TextBlock.Text>
  4.         <Binding ElementName="textBox1" Path="Text"/>
  5.     </TextBlock.Text>
  6. </TextBlock>

2.キー入力をプログラムの変数に反映する

  INotifyPropertyChanged インタフェースを継承した変数用のクラスを使います。
  これは、双方向に使えます。
  次の例を参照ください。

  確認できたのは、TextBox に値を入力しても、変数は書き換えられません。
  TextBoxに対する操作ではなく、Buttonがクリックされるなど、アプリケーションに制御が渡るときに、変数が更新されます。

3.プログラムの変数を変えると表示が変わる

このサンプルは、TextBox、TextBlock、Buttonの3つのコントロールを配置してあります。

TextBlockのTextプロパティは、TextBoxのTextプロパティにバインドしてあります。
TextBoxに文字を入力するごとに、TextBlockにも同様に表示されます。
この動作は、XAMLの記述だけで実現されています。
1.で説明したものです。
 

   プログラムの変数との連携には、変数を含むクラスが INotifyPropertyChanged インタフェースを持つことが必要です。

 XAML

  1. <Window x:Class="WpfApplication2.Window1"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     Title="Window1" Height="300" Width="300">
  5.     <Grid Loaded="LayoutRoot_Loaded" Width="200" Height="100">
  6.         <Grid.RowDefinitions>
  7.             <RowDefinition Height="50"/>
  8.             <RowDefinition Height="50"/>
  9.         </Grid.RowDefinitions>
  10.         <Grid Grid.Row="0"><!--上の段-->
  11.             <Grid.ColumnDefinitions>
  12.                 <ColumnDefinition Width="100"/>
  13.                 <ColumnDefinition Width="100"/>
  14.             </Grid.ColumnDefinitions>
  15.             <TextBox Name="textBox1"  Grid.Column="0" Text="{Binding bind_string}"/>
  16.             <TextBlock Grid.Column="1">
  17.                 <TextBlock.Text>
  18.                     <Binding ElementName="textBox1" Path="Text"/>
  19.                 </TextBlock.Text>
  20.             </TextBlock>
  21.             </Grid>
  22.         <Grid Grid.Row="1"><!--下の段-->
  23.             <Button Grid.Row="1" Content="{Binding bind_string}" Click="Button_Click"/>
  24.         </Grid>
  25.     </Grid>
  26. </Window>

  バインドする変数はプロパティとして定義します。
  この例では、Class1 に、bind_string と言う string型のプロパティを置きました。
  class 宣言が public になっていません。これでも動作しましたが、Silverlight では、public 宣言は必須です。

  いつ更新されるのかを観察するために、Debug.WriteLine() が入れてあります。
  このプロパティが set されたら、PropertyChanged.Invoke() で、表示への通知が行われます。

  #region 内は、INotifyPropertyChanged にカーソルを置いて、右ボタンメニューの「インタフェースの実装」で追加されたものです。

  XAML では、bind_string を、TextBoxのText と ButtonのContent にバインドしています。
  Button の Click イベントで、bind_string に値を代入しているので、Button をクリックすると、TextBox と Button の表示文字列が同じ内容に変わります。

  XAML の記述で、bind_string は、どこから探されるのかですが、Grid など、親の DataContext です。
  上位であれば良く、直上である必要はないようです。

 Class1

  1. using System.ComponentModel;
  2. using System.Diagnostics;
  3. namespace WpfApplication2
  4. {
  5.     class Class1 : INotifyPropertyChanged
  6.     {
  7.         string _bind_string="";
  8.         public string bind_string
  9.         {
  10.             get { return _bind_string; }
  11.             set
  12.             {
  13.                 _bind_string = value;
  14.                 Debug.WriteLine(_bind_string);
  15.                 if (PropertyChanged != null)
  16.                     PropertyChanged.Invoke(this, new PropertyChangedEventArgs("bind_string"));
  17.             }
  18.         }
  19.         #region INotifyPropertyChanged メンバ
  20.         public event PropertyChangedEventHandler PropertyChanged;
  21.         #endregion
  22.     }
  23. }

  ビハインドコードで、Class1のオブジェクトをDataContextに設定しました。
  Button が Click されたら、bind_string に、文字 a を連結して代入するようにしました。

 ビハインドコード

  1. using System.Windows;
  2. namespace WpfApplication2
  3. {
  4.     public partial class Window1 : Window
  5.     {
  6.         public Window1()
  7.         {
  8.             InitializeComponent();
  9.         }
  10.         Class1 c1;
  11.         private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
  12.         {
  13.             c1 = new Class1();
  14.             this.DataContext = c1;
  15.         }
  16.         string _text = "";
  17.         private void Button_Click(object sender, RoutedEventArgs e)
  18.         {
  19.             _text += "a";
  20.             c1.bind_string = _text;
  21.         }
  22.     }
  23. }

  DataContext を、Grid の Loaded イベントで設定しましたが、XAMLで設定することもできます。

 DataContext をXAMLで設定する例

  1. <Window x:Class="WpfApplication2.Window1"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     xmlns:c0="clr-namespace:WpfApplication2"
  5.     Title="Window1" Height="300" Width="300">
  6.     <Grid Name="LayoutRoot" Width="200" Height="100">
  7.         <Grid.DataContext>
  8.             <c0:Class1/>
  9.         </Grid.DataContext>
  10.         <Grid.RowDefinitions>
  11.             <RowDefinition Height="50"/>

  この場合は、Loaded イベントの処理は不要になりますが、コードで Class1 のオブジェクトを作っていないので、変数の操作は不自由です。

  1. using System.Windows;
  2. namespace WpfApplication2
  3. {
  4.     public partial class Window1 : Window
  5.     {
  6.         public Window1()
  7.         {
  8.             InitializeComponent();
  9.         }
  10.         string _text = "";
  11.         private void Button_Click(object sender, RoutedEventArgs e)
  12.         {
  13.             _text += "a";
  14.             ((Class1)LayoutRoot.DataContext).bind_string = _text;
  15.         }
  16.     }
  17. }


mikeo_410@hotmail.com