Part 1. 双方向データバインドの基本的な使い方


Windows フォームにおけるデータ入力において、スマートに単体入力エラーチェックを行いたい場合には、双方向データバインドと IDataErrorInfo インタフェースを利用する方式が便利です。ただし、この Windows フォームのデータバインドは Web フォームのデータバインドとは大きく異なる点があります。



  • 双方向データバインドが利用できる。(※ Web フォームでも使えますが、極めて限定的です。)

  • 入力データのデータソースへの反映がリアルタイムに行われる。(リアルタイムにデータが同期。)

このため、ASP.NET Web アプリケーションでのデータバインドにすでに慣れ親しんでいる方でも、Windows フォームのデータバインドについては、全く新しい技術として学習しなおす、ぐらいの感覚で取り組むことが重要です。今回のエントリでは、まず基本的な Windows フォームのデータバインドの実装方法を解説したいと思います。具体的な解説トピックは以下の通りです。



  • 双方向データバインドとは何か

  • 2 種類のデータバインド

  • データバインドの基本的な使い方 : データソースとなりうるオブジェクト

  • データバインドの基本的な使い方 : 単票形式データバインド

  • データバインドの基本的な使い方 : グリッド形式データバインド

  • null 値の入力制御方法(パース処理のカスタマイズ方法)

なお、今回のサンプルを最後まで実装したサンプルコードはこちらになります。併せてご利用ください。



では、以下に解説していきます。


[双方向データバインドとは何か]


双方向データバインドとは、UI コントロール(DataGrid や TextBox, Label コントロールなど)の特定のプロパティと、データソースとなるオブジェクト(型付きデータセットやカスタムオブジェクト)とを紐づけておき、



  • データソースから自動的にデータを抽出して UI コントロールに表示する。

  • UI コントロールから入力された値を、自動的にデータソースに反映する。

という動作をさせるものになります。


image 


ASP.NET Web フォームなどのデータバインドでは、ほとんどの場合、データソース内のデータを UI コントロールに表示するという目的のみで利用されます。このため、更新系アプリケーションにおけるデータ入力シートを作成する目的でデータバインドを使うことはまずありません、しかし、Windows フォームや WPF などでは、更新系アプリケーションにおけるデータ入力画面を作成する際に、今回解説する双方向データバインドを利用します


例えば、下図のような新規顧客登録画面を作ろうと思った場合を考えてみてください。ASP.NET Web フォームの場合には、通常のテキストボックスと検証コントロール(Validation Control)によりこのような画面の単体入力チェック機能を作るはずです。しかし、Windows フォームの場合には、検証コントロールは使いません(というより存在しません)。このような場合に、双方向データバインドと IDataErrorInfo インタフェースを利用して、単体入力チェック機能を実装します。



  • ASP.NET Web フォームの場合 : 検証コントロールで実装
    image

  • Windows フォームの場合 : 双方向データバインドと IDataErrorInfo で実装
    image

この双方向データバインドによるエラーチェックは、単票形式でもグリッド形式でもどちらでも利用可能ですが、いきなりこれらの解説に入る前に、まずは Windows フォームによるデータバインドの基本についてもう少し解説しましょう。


[2 種類のデータバインド]


上にちょろっと書いたように、データバインドには、単票形式のデータバインドと、グリッド形式のデータバインドの 2 種類があります。(ちなみにこの分類方法は、Windows フォームだけでなく WPF でも同じです。)



  1. 単一値データバインド (単票形式のデータバインド)
    データソースとして、「あるオブジェクトインスタンス(の一つ)」を使うもの

  2. コレクションデータバインド (グリッド形式のデータバインド)
    データソースとして、「オブジェクトインスタンスのコレクション」を使い、一括表示するもの

image


基本的に単一値データバインド(単票形式データバインド)は、1 レコード分のデータを保有するオブジェクトインスタンスを、単票形式に表示するためのものです。そしてこれを n 回、縦方向に繰り返したものがコレクションデータバインド(グリッド形式データバインド)になります。このため、まずは単一値データバインド(単票形式データバインド)のことを正しく理解することが重要です。これを正しく理解すれば、コレクションデータバインドもおのずと理解できるようになります。


[データバインドの基本的な使い方 : データソースとなりうるオブジェクト]


さて、データバインドは、UI コントロール(バインドされたデータを表示する UI 部品) とデータソースオブジェクト(実際のデータとなるもの)とが、BindingSource オブジェクト(データバインドを制御するもの)により連結制御されることにより実現されます。


image 


よって、このような連結関係を組み立て上げればデータバインドが使えるようになるのですが、このデータバインドのデータソースとして利用できる代表的なオブジェクトとしては、以下の 2 つがあります。これについて解説しておきましょう。



  • カスタムオブジェクトおよびそのコレクション

  • 型付きデータ行および型付きデータテーブル

① カスタムオブジェクトおよびそのコレクション


public フィールドや public プロパティを持つオブジェクトは、そのまま単票形式にバインド(単一値データバインド)することができます。具体的には、下図のサンプルに示すようなクラスのインスタンスを単票形式データバインドのデータソースに、またそのコレクションをグリッド形式データバインドのデータソースに利用できます。


image


② 型付きデータ行および型付きデータテーブル


また、.xsd ファイルを用いて作成できる型付きデータセットの中に含まれる、型付きデータテーブルと型付きデータ行は、それぞれグリッド形式データバインドと単票形式データバインドに利用できます。


image


②の型付きデータセットや型付きデータテーブルを利用するデータバインドについては、ASP.NET Web フォームにおけるデータ表示用データバインドなどでもお馴染みだと思います。しかし、Windows フォームでデータバインドを行う場合、



  • データ表示しか行わない場合には、②を利用する。

  • 表示したデータをユーザに更新させる場合には、①を利用する。

という使い分けを行います。特に後者が重要で、Windows フォームで更新系アプリケーションを作る場合には、型付きデータセットを使った双方向データバインドは行いません。このことを頭の片隅に置いておいてください。(理由はおいおいわかってくると思いますが、簡単に記述すると、型付きデータセットを使うと単体入力データ検証ロジックの実装が分かりづらくなるからです。)


では引き続き、具体的なデータバインドの実装方法(Visual Studio 2008の使い方)について解説していきます。今回の blog エントリのゴールは単体入力チェック機能を持つデータ入力ページを作成することであるため、①の方法を中心に解説します。また、ここではまだ単体入力チェック機能は実装しません。まず、双方向データバインドの組み立て方(BindingSource オブジェクトによる連結方法)に絞って解説します。


[データバインドの基本的な使い方 : 単票形式データバインド]


まずは単票形式のデータバインドから解説していきましょう。具体的には、以下の 4 つの作業を行います。



  1. データバインドするオブジェクトの準備

  2. データソースの登録

  3. BindingSource コントロールの貼り付け

  4. データの紐付け

ここでは、以下のような画面を双方向データバインドで組み上げる方法について解説します。


image


Step 1. データバインドするオブジェクトの準備


まず、UI とバインドを行うためのクラスを作成します。具体的には、新規に Windows フォームアプリケーションプロジェクトを作成し、TitleInput.cs という名前でクラスを追加します。


image


ここに、データ 1 レコード分に相当するオブジェクトのクラスを定義します。なお、null 入力値を受け付けるフィールドについては、Nullable<T> 型で定義をしてください。



   1: namespace WindowsFormsApplication1
   2: {
   3:     public class TitleInput
   4:     {
   5:         public string title_id { get; set; }
   6:         public string title { get; set; }
   7:         public decimal? price { get; set; }
   8:         public DateTime? pubdate { get; set; }
   9:     }
  10: }

Step 2. データソースの登録


次に、Visual Studio でビジュアルデザイン機能を利用できるようにするため、データソース登録を行います。以下の作業を行ってください。



  • プロジェクト全体をまずリビルドする。

  • ツールバーの「データ」→「データソースの表示」を行って、データソースウィンドウを表示する。

  • データソースウィンドウ内の「新しいデータソースの追加」をクリックする。

  • データソース構成ウィザードが起動するので、TitleInput オブジェクトを選択する。

image


これにより、データソースウィンドウに、TitleInput クラスのデータ構造情報が取り込まれ、GUI からのデータバインド設定操作ができるようになります。


Step 3. BindingSource コントロールの貼り付け












次に、単票形式の画面を作成します。具体的には、以下の作業を行います(が、できればウィザードを使わないでできるようになってほしいので、まずは後述する方法を使ってください)。



  • Form1.cs のデザイン画面を開く。

  • データソースの TitleInput の貼り付け方式を「DataGridView」から「詳細」に切り替えた上で、フォーム上にドラッグ&ドロップする。

  • 単票形式のデータバインドの場合、BindingNavigator コントロールは不要なので削除する。

  • あとは適宜、画面を編集する。(ラベルの追加やボタンの追加など)

image


実際の開発では上記の作業を行っていくのですが、これだとウィザードがかなりの部分を自動的にやってしまうので、何をやっているのかがわからないと思います。以下のようにすると、上記の作業をきちんと一つずつ手作業で行うことができます。最初のうちはこちらの方法でやってください。



  • BindingSource コントロールを画面に貼り付ける。

  • BindingSource コントロールの DataSource プロパティに、作業 2. でデータソース登録したクラス(この例の場合は TitleInput クラス)を指定する。(この作業により、以降のステップで、データソースのプロパティとの紐づけが GUI から簡単に設定できるようになる)
    image

  • 画面上に、ラベルやテキストボックスを貼り付けて並べていく。

  • データバインド対象となる UI コントロール(例えばテキストボックスなど)の DataBindings プロパティを開き、データソースオブジェクトのターゲットプロパティとの紐づけ関係を指定する。
    image

Step 4. データの紐付け


最後に、フォームのロードイベントなどにデータの紐づけコードを作成します。具体的には、以下の作業を行います。



  • フォームの private メンバ変数として、データバインドするオブジェクトインスタンスの変数を宣言しておく。(下記コードの _data 変数)

  • Form_Load() メソッド内で、データバインドするオブジェクトインスタンスを作成し、BindingSource コントロールに割り当てる。


   1: public partial class Form1 : Form
   2: {
   3:     public Form1()
   4:     {
   5:         InitializeComponent();
   6:     }
   7:  
   8:     private TitleInput _data;
   9:  
  10:     private void Form1_Load(object sender, EventArgs e)
  11:     {
  12:         this._data = new TitleInput()
  13:         {
  14:             title_id = “BU1032”,
  15:             title = “Book of .NET”,
  16:             price = 30,
  17:             pubdate = new DateTime(1973, 6, 7)
  18:         };
  19:         this.bindingSource1.DataSource = this._data;
  20:         // ※ ウィザードで作成した場合は
  21:         // this.titleInputBindingSource.DataSource = this._data;
  22:     }
  23: }

以上の作業により、下図のようなデータバインドが構成され、画面上にデータの内容が自動的に表示されるようになります。



  • UI 画面と BindingSource コントロールとデータソースオブジェクトの関係
    image

  • 実行結果
    image

なお、注意していただきたいのは Step 3 と Step 4 で行うプロパティへの設定の違いです。



  • Step 3 では、BindingSource コントロールの DataSource プロパティに、データソースウィンドウで設定した TitleInput クラスを設定している。

  • Step 4 では、BindingSource コントロールの DataSource プロパティに、実際に Form_Load() イベント内で作成した TitleInput オブジェクトのインスタンスを割り当てている。

実際に UI 画面上にデータを表示するためには、DataSource プロパティにオブジェクトのインスタンスを割り当てなければなりません(Step 4)。しかしながら、UI 画面のデザイン時には、まだオブジェクトインスタンスが作成されていません。そこで、UI 画面のデザイン時(Step 3)には、インスタンスのかわりにクラスを割り当てておくことで、デザイン機能を有効化する、というわけです。


現時点での実装上の問題


ここまでで、_data 変数の内容が自動的に UI 上に表示されることが確認できましたので、今度は UI からの入力がデータソースである _data 変数に反映されることを確認してみましょう。まず、button1_Click() メソッドに以下のような処理を組み込んでおきます。



   1: private void button1_Click(object sender, EventArgs e)
   2: {
   3:     MessageBox.Show(
   4:         “書籍ID : “ + _data.title_id + “\n” +
   5:         “書籍名 : “ + _data.title + “\n” +
   6:         “価格   : “ + _data.price + “\n” +
   7:         “出版日 : “ + _data.pubdate);
   8: }

その上で、以下のような作業をしてみてください。



  • 不適切なデータの入力
    書籍 ID に不適切なコードを入力したり、価格にマイナスの値を入力しても、問題なく入力が通り、そのまま背後の _data 変数に入力内容が反映されてしまいます。

  • フォーカス制御(フォーカス移動の抑止)
    例えば、価格欄に “ABC” などの型変換ができないデータを入力した場合には、フォーカス移動ができなくなります。

  • null 値の入力
    価格や出版日は null 値が設定できるはずですが、入力を空欄(空文字 “”)にしても、null 値が設定されません。

image


確かに、UI からの入力内容は BinidngSource コントロールによりデータソースに反映されています。しかしながら、空文字として入力された値を null 値に変換したり、不適切なデータ入力を抑止させたりするといった制御が行われておらず、このままでは業務アプリケーションのデータ入力フォームとしては利用できません。(これらの問題の解決方法については後述します。)


 


 


 


 


では引き続き、グリッド形式のデータバインドの実施方法の基本を解説します。


 


[データバインドの基本的な使い方 : グリッド形式データバインド]


グリッド形式のデータバインドには、通常 DataGridView コントロールを利用します。具体的には、以下の作業を行います。



  1. データバインドするオブジェクトの準備

  2. データソースの登録

  3. DataGridView コントロールの貼り付けとデータソースの指定

  4. DataGridView の表示列のカスタマイズ

  5. データソースへのコレクションの割り当て

これについて解説します。


1. データバインドするオブジェクトの準備、2. データソースの登録


先に解説したように、コレクションデータバインドは単一値データバインドの n 件繰り返しになります。このため、データソースとして利用するオブジェクトは、先の単票形式データバインドの場合とまったく同じになります。1 レコード分に相当するオブジェクトとして TitleInput クラスを作成し、データソースとして登録を行っておいてください。


3. DataGridView コントロールの貼り付けとデータソースの指定


次に、コレクションデータバインドを行う画面を作ります。アプリケーションにもうひとつフォームを追加し、以下の作業を行います。


image 



  • BindingSource コントロールと DataGridView コントロールを貼り付ける。

  • bindingSource1 の DataSource プロパティに、TitleInput クラスを指定する。

  • dataGridView1 の DataSource プロパティに、bindingSource1 インスタンスを指定する。

以上の作業により、下図のようなプレビュー画面が表示されます。


image


4. DataGridView の表示列のカスタマイズ


次に、DataGridVIew のタスクペイン(コントロールの右上に表示される小さな矢印から開かれるタスク一覧)から列の編集を行います。これにより、表示列の絞り込みや、列ヘッダーや列幅、表示フォーマットなどの調整ができます。(※ 価格列については、DefaultCellStyle プロパティを変更すると通貨表示ができます。)


 


 


image


image


image


5. データソースへのコレクションの割り当て






最後に、Form_Load() イベントなどで、bindingSource1 の DataSource プロパティにて、実際に画面上に表示するデータコレクションを割り当てます。(なお、今回は簡単のため、データをその場で作成して割り当てますが、実際の業務アプリケーションでは、XML Web サービスなどからデータを取り寄せて、そのデータを紐づけ表示することになります。)



   1: public partial class Form2 : Form
   2: {
   3:     public Form2()
   4:     {
   5:         InitializeComponent();
   6:     }
   7:  
   8:     private List<TitleInput> _dataItems;
   9:  
  10:     private void Form2_Load(object sender, EventArgs e)
  11:     {
  12:         _dataItems = new List<TitleInput>()
  13:         {
  14:             new TitleInput() { title_id=“BU1032”, title=“Book of .NET”, 
  15:             price=10.0m, pubdate=new DateTime(1973, 6, 7) },
  16:             new TitleInput() { title_id=“PT0572”, title=“All About MSFT”, 
  17:             price=5.9m, pubdate=new DateTime(2008, 5, 3) }
  18:         };
  19:         bindingSource1.DataSource = _dataItems;
  20:     }
  21: }

なお、DataSource プロパティの割り当てを行う場合には、dataGridView1.DataSource プロパティではなく、bindingSource1.DataSource プロパティへの割り当てを行ってください。このサンプルでは、紐付け関係を明示的に bindingSource1 コントロールにより下図のように制御しているためです。


image


実行結果を以下に示します。


image


なお、このサンプルでもやはり先に示した単票形式のサンプルと同様、以下のような問題があります。


  • 不適切なデータの入力

  • フォーカス制御(フォーカス移動の抑止)

  • null 値の入力

    これらのうち、不適切なデータ入力の問題やフォーカス制御の問題については次回以降のエントリで詳細に解説していきますが、null 値の入力の取り扱い方法に関しては本エントリで解説してしまうことにします。


    [null 値の入力制御方法(パース処理のカスタマイズ方法)]


    一般に、データ入力フォームにおいて null 設定を可とするプロパティに対して、どのようにしてエンドユーザに null 値を入力させるのかに関しては、かなり頭の痛い問題を抱えています。今回取り扱った例を考えてみましょう。


    image


    このケースでは、書籍 ID や書籍名のフィールドは string 型であるため null 値が設定できるはずです。しかし、TextBox との双方向データバインドが行われている場合、



    • データソースが null の場合、テキストボックスへの表示は “” (空文字)になる。

    • データソースが “” (空文字)の場合も、テキストボックスへの表示は “” (空文字)になる。

    • では、テキストボックスの入力が “” (空文字)の場合は、これをデータソースにどのように反映するべきか?(null として反映すべきか、それとも空文字として反映すべきか?)

     


     


     


    という問題があり、状況やバインド対象データによる case-by-case の判断が必要になります。


    実はこうした問題を回避するため、SQL Server Management Studio や DataGridView コントロールでは、”Ctrl + 0” という特殊入力機能を備えています。下図に示すように、一覧表示された表の上で “Ctrl + 0” を押すと、そのフィールドに null 値が設定できるようになっています。


    image


    しかし、この “Ctrl + 0” による null 入力機能には、以下のような制約があります。



    • TextBox をはじめとする大半のコントロールではこの機能を利用できない。(例えば DateTimePicker などでは当然使えない)

    • DataGridView に関しては、型付きデータセットや型なしデータセットとバインドする場合のみこの機能が利用できる。カスタムオブジェクトの持つ Nullabe<T> フィールドとのバインドの際にはこの機能をできない。

    現実的な話として、



    • テキストボックスなどからの空文字入力を “” (空文字)と解釈すべきか null 値と解釈すべきかは状況やバインド対象データによって変わる。

    • たとえば価格データなどについては空文字をストレートに decimal? の null と解釈してくれた方がユーザにとって使いやすいアプリとなる。

    • エンドユーザに ”Ctrl + 0” 入力方式をお願いすることは非現実的。

    などを考慮すると、テキストボックスからの入力値を必要に応じてパースし、空文字入力を null 値として解釈しなおすような処理を作り込んだ方が現実的でしょう。具体的には以下のようなことを知っておくと便利です。



    1. TextBox コントロールからの空文字入力を null 値に変換してデータソースに反映する方法

    2. (応用例) ドロップダウンリストからの入力値をデータソースに反映する方法

    3. 空文字入力を null 値に自動変換する NullableTextBox コントロールを作る方法

    4. DataGridView にて空文字入力を null 値に変換する方法

    これらについて解説します。


    1. TextBox コントロールからの空文字入力を null 値に変換してデータソースに反映する方法


    TextBox コントロールからの空文字入力を null 値に変換する最も簡単な方法は、データソースへの反映制御をつかさどっている BindingSource コントロールのパース処理をカスタマイズすることです。具体的には、価格テキストボックスに紐づけられているバインディングオブジェクトを取り出し、パース処理のイベントをフックします。具体的には、以下のようなコードを記述します。



       1: public partial class Form1 : Form
       2: {
       3:     private void Form1_Load(object sender, EventArgs e)
       4:     {
       5:         … (中略) …
       6:         Binding b = priceTextBox.DataBindings[“Text”];
       7:         b.Parse += new ConvertEventHandler(b_Parse);
       8:     }
       9:  
      10:     void b_Parse(object sender, ConvertEventArgs e)
      11:     {
      12:         if (e.Value as string == “”)
      13:         {
      14:             e.Value = null;
      15:         }
      16:     }

    このようにすると、下図のように、空文字入力した内容が自動的に null 値に変換されてデータソースオブジェクト(_data 変数)に反映されるようになります。


    image 


    2. (応用例) ドロップダウンリストからの入力値をデータソースに反映する方法


    このようなパース処理のカスタマイズは、特にドロップダウンリストからの入力値をデータソースに反映するような場合に役立ちます。例えば、下図の例を見てください。


    image


    この例では、契約有無による契約条件をドロップダウンリストから選択させています(空文字、「契約あり」「契約なし」の 3 つから選択)。この値を、これを背後にあるオブジェクトの bool? contract プロパティへと反映したい場合には、string 型から bool? 型への変換が必要になります。このような変換も、Binding オブジェクトの Parse イベントのフックにより実現できます。具体的には以下のようなコードを書きます。



       1: private void FindAuthors_Load(object sender, EventArgs e)
       2: {
       3:     … (中略) …
       4:     Binding cbxContractBinidng = cbxContract.DataBindings[“Text”];
       5:     cbxContractBinidng.Parse += new ConvertEventHandler(cbxContractBinidng_Parse);
       6: }
       7:  
       8: void cbxContractBinidng_Parse(object sender, ConvertEventArgs e)
       9: {
      10:     switch (e.Value as string)
      11:     {
      12:         case “”:
      13:             e.Value = null;
      14:             break;
      15:         case “契約あり”:
      16:             e.Value = true;
      17:             break;
      18:         case “契約なし”:
      19:             e.Value = false;
      20:             break;
      21:         default:
      22:             throw new ApplicationException(e.ToString());
      23:     }
      24: }
      25:  

     


     


     


     


    3. 空文字入力を null 値に自動変換する NullableTextBox コントロールを作る方法


    さて、このように Parse イベントを作り込めば、背後のオブジェクトへの反映方法を自由にカスタマイズできるのですが、空文字 → null 値への変換を行う TextBox は比較的頻出です。このため、TextBox コントロールを継承した NullableTextBox コントロールを作って使ってしまった方がラクでしょう。具体的には以下の作業を行います。



    • 適当なフォルダに、NullabeTextBox という名前でクラスファイルを一つ作成する。

    image



    • TextBox クラスを継承したクラスを作成し、Text プロパティをオーバライドする。


       1: using System;
       2: using System.Collections.Generic;
       3: using System.Linq;
       4: using System.Text;
       5:  
       6: using System.Windows.Forms;
       7: using System.ComponentModel;
       8:  
       9: namespace MCS.Japan.Framework.Client.WinForms
      10: {
      11:     public class NullableTextBox : TextBox
      12:     {
      13:         [DefaultValue(null)]
      14:         public override string Text
      15:         {
      16:             get
      17:             {
      18:                 return ((base.Text == “”) ? null : base.Text);
      19:             }
      20:             set
      21:             {
      22:                 base.Text = ((value == null) ? “” : value);
      23:             }
      24:         }
      25:  
      26:         [Browsable(false)]
      27:         public new string[] Lines
      28:         {
      29:             get
      30:             {
      31:                 throw new InvalidOperationException(“NullableTextBox では Lines プロパティへのアクセスを認めていません。”);
      32:             }
      33:         }
      34:     }
      35: }


    • リビルドすると、ツールボックスから貼り付けられるようになるので、これを利用する。(バインドの指定方法などは通常の TextBox などと同じです。)

    image


    4. DataGridView にて空文字入力を null 値に変換する方法




    さてテキストボックスの場合には、null 値の入力を可能にする方法として、パース処理をカスタマイズする方法と、NullableTextBox を作成する方法があることを解説しました。しかし、DataGridView の場合には制約があり、前者のパース処理のカスタマイズによる null 値変換の方法を取れません(詳細はこちら)。このため、DataGridView の特定列を null 入力可にするためには、空文字入力を null 値として解釈するような列クラスを作成し、これを利用する必要があります。具体的には以下のようにします。



    • 適当なフォルダに、DataGridViewNullableTextBoxColumn.cs クラスを追加する。

    image



    • null 入力を可能にするようなテキストボックスセルとテキストボックス列を作成する。


       1: using System;
       2: using System.Collections.Generic;
       3: using System.Linq;
       4: using System.Text;
       5: using System.Windows.Forms;
       6: using System.ComponentModel;
       7:  
       8: namespace MCS.Japan.Framework.Client.WinForms
       9: {
      10:     public class DataGridViewNullableTextBoxColumn : DataGridViewTextBoxColumn
      11:     {
      12:         public DataGridViewNullableTextBoxColumn()
      13:         {
      14:             this.CellTemplate = new DataGridViewNullableTextBoxCell();
      15:         }
      16:  
      17:         public override DataGridViewCell CellTemplate
      18:         {
      19:             get
      20:             {
      21:                 return base.CellTemplate;
      22:             }
      23:             set
      24:             {
      25:                 if ((value is DataGridViewNullableTextBoxCell) == false)
      26:                 {
      27:                     throw new InvalidOperationException(“DataGridViewTextBoxCell以外は指定できません。”);
      28:                 }
      29:                 base.CellTemplate = value;
      30:             }
      31:         }
      32:     }
      33:  
      34:     public class DataGridViewNullableTextBoxCell : DataGridViewTextBoxCell
      35:     {
      36:         protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
      37:         {
      38:             if (value == null) return null;
      39:             return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
      40:         }
      41:  
      42:         public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
      43:         {
      44:             if ((formattedValue as string) == “”) return null;
      45:             return base.ParseFormattedValue(formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
      46:         }
      47:     }
      48: }

     



    • リビルドを行った上で DataGridView コントロールの列定義を開き、列のデータ型として、作成した NullableTextBoxColumn を割り当てる。

    image [


    以上により、空文字入力を null 値として解釈してくれる列を作成することができます。


    image


    [今回のエントリのまとめ]


    というわけで、Part 1. では、双方向データバインドの基本的な使い方を解説してきました。キーポイントをまとめると、以下の通りとなります。



    • 双方向データバインドを用いると、データソースから UI コントロールへ値を表示するだけでなく、UI コントロールからの入力をデータソースに反映できる。

    • データバインドには、2 種類のデータバインドがある。
      ① 単一値データバインド(単票形式データバインド)
      ② コレクションデータバインド(グリッド形式データバインド)

    • どちらの場合も、BindingSource コントロールを介して、UI コントロールとデータソースを紐づける。

    image


    さて、今回のエントリでは UI からの入力値をデータソースへと反映する双方向データバインドの基本動作を解説しましたが、実際には反映できたからといってその入力値が正しいとは限りません。データ入力値が正しくない場合には、入力エラーメッセージを画面上に表示する必要がありますが、この方法については次のエントリで解説していきたいと思います。


     


     


     


     

  • Comments (1)

    1. ふと気付いてみれば前回のエントリから一か月以上が経過。一回サボるとついエントリをサボり気味になってしまうものですね;。さて今度のエントリは何にしようかと迷っていたのですが、先日、マイミクの Gushwell

    Skip to main content