2009-08-13 14 views
4

Windowsフォーム(.NET 2.0、Visual Studio 2005 SP1):タイプがであり、タイプがSystem.Booleanであり、nullableで、デフォルト値はDBNullです。私はFormを持っています。これは、先の列の値にバインドするコントロールCheckBoxを含んでいます。CheckBoxをNULL入力可能なbool型DbColumnにバインドする方法はありますか?

  • 私はデザイナーを経て、列にCheckedプロパティをバインドしようとしている:それは素晴らしい作品、列のデフォルト値はTrueまたはFalseのいずれかに設定されている場合のみ。
  • は私がデザイナーを経て、カラムへCheckStateプロパティをバインドしようとしました、そして私自身のFormatParseイベントハンドラを取り付けるが、彼らは決して呼ばれることはありません飽きてきた:私はカスタムを作成しようとしました

    b.Format+=delegate(object sender, ConvertEventArgs cevent) { 
        cevent.Value=DoFormat((CheckState)cevent.Value); // cf. end of the question 
    }; 
    b.Parse+=delegate(object sender, ConvertEventArgs cevent) { 
        cevent.Value=DoParse(cevent.Value); // cf. end of the question 
    }; 
    
  • Bindingコード内のインスタンスは、私のイベントハンドラを添付し、CheckBoxバインディングに追加します。イベントハンドラはまだ呼び出されない飽きないさ...

    Binding b=new Binding("CheckState", _BindingSource, "MyColumn", false, DataSourceUpdateMode.OnPropertyChanged, DBNull.Value); 
    

注記:DBNullの値は、DataSet(値が設定されていないことを意味します)からの場合に限り受け入れられます。ただし、ユーザはまたはFalseに値を設定することができるのはCheckBoxです。 、私が知っているeasist方法

internal static CheckState DoParse(object value) 
{ 
    if ((value==null) || (value is DBNull)) 
     return CheckState.Indeterminate; 

    bool v=Convert.ToBoolean(value); 
    return (v ? CheckState.Checked : CheckState.Unchecked); 
} 

internal static object DoFormat(CheckState value) 
{ 
    switch (value) 
    { 
    case CheckState.Checked: 
     return true; 
    case CheckState.Indeterminate: 
     return DBNull.Value; 
    case CheckState.Unchecked: 
     return false; 
    } 

    return null; 
} 
+0

**私の答えの終わりまで**の情報が追加されました。 –

答えて

7

はあなたが解析への添付なしのDataColumnにCheckBox.CheckStateを結合し、書式イベントまたは結合をいじってみましたがありますか?

残念ながら、私は可能なのVisual Studio 2005のインスタンスを持っていないが、私は、Visual Studio 2008で迅速なフォームを組み立て、それはあなたが指定したまさにをした:はDBNull値:注意点としては

DataSetから来るときだけ許容されます(値が一度も設定されていないことを意味します)。しかし、ユーザーは、CheckBoxを使用して値をTrueまたはFalseに設定できるだけです。

私が解析、フォーマットまたはあなたの方法あるいはそれになっバインディングは、Windowsフォームが


2005年に比べ2008年には異なった動作をすることをかもしれかもしれUPDATE 8月18日: それは上の作品Visual Studio 2005も、デザイナーとコードの両方で使用できます。 は、ここでは、作業を示すコードです:


using System; 
using System.Data; 
using System.Drawing; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 { 
    public partial class Form1 : Form { 
     DataTable table = new DataTable(); 
     public Form1() { 
      InitializeComponent(); 

      //Creates the table structure 
      table.Columns.Add("Name", typeof(string)); 
      table.Columns.Add("MyColumn", typeof(bool)); 

      //Populates the table with some stuff 
      for (int i = 0; i < 5; i++) { 
       table.Rows.Add(i.ToString()); 
      } 

      //Creates the controls and puts them on the form. 
      TextBox textBox = new TextBox(); 
      textBox.Location = new Point(10, 10); 
      textBox.DataBindings.Add("Text", table, "Name"); 

      CheckBox checkBox = new CheckBox(); 
      checkBox.Left = textBox.Left; 
      checkBox.Top = textBox.Bottom + 10; 

      //Without true on the last argument, it will not work properly. 
      checkBox.DataBindings.Add("CheckState", table, "MyColumn", true); 

      Button previous = new Button(); 
      previous.Text = ""; 
      next.Top = previous.Top; 
      next.Left = previous.Right + 5; 
      next.Click += new EventHandler(next_Click); 

      this.Controls.AddRange(new Control[] { textBox, checkBox, previous, next }); 
     } 

     void next_Click(object sender, EventArgs e) { 
      this.BindingContext[this.table].Position++; 
     } 

     void previous_Click(object sender, EventArgs e) { 
      this.BindingContext[this.table].Position--; 
     } 
    } 
} 


UPDATE 8月23日:

それはバインディング

を取得する責任があるFormatObjectと呼ばれるプライベートメソッドを持って働く理由コントロールに表示されるのに適したデータソースからの値の表現。

フォーマットが有効な場合、Binding.FormatObject()は、Binding.Formatイベントの最終的なハンドラを呼び出すコードパスを実行します。ハンドラによってConvertEventArgs.Valueを介してデータソースからコントロールに伝播される値が変更されると、その値が使用されます。それ以外の場合は、System.Windows.Forms.Formatterという内部クラスに対してFormatObjectという既定のフォーマッタが呼び出されます。

ソースコードの状態に関するコメント:

「真の変換作業がFormatObjectInternal(内部で起こる)」

FormatObjectInternal状態のコメント:

「は、例えば(いくつかの特別なケースの変換を実行します。ブール値からCheckStateへ) "

FormatObjectInternalの内部では、データソースからの値がnullかDBNullかどうかをチェックし、そうである場合は、バインドされるプロパティはCheckStateです。そのような場合は、CheckState.Indeterminateを返します。

このように、これはWindowsフォーム1.xではうまくいきませんでした。幸いなことに、それは2.0以降で修正されました。

+0

ブーリアンデータを列挙型(3つの可能な値!)にバインドするのは頭が痛いと思いますが、とにかく好奇心から試してみます... – Mac

+0

私はVisual Studio 2005を試してみました。働いた。 デザイナー経由でもコード経由でも。 –

+0

サンプルは機能しますが、この質問に対しては正しくありません。 @Macは "DBNullは行からコントロールに移入できますが、コントロールから行に移入することはできません"。 "MyColumn"と "CheckState"の間のデータバインディングはそれを実現しません。正しい動作のためには、Format/Parseイベントをフックし、渡す値を編集する必要があります。 @Maxが頻繁に書いたようなシナリオであれば、再利用可能な解決策を使うことをお勧めします。 – TcKs

1

はDBNull値を処理してバインドすることができ、「DataValueは、」プロパティを追加し、CheckBoxクラスから派生です:

参考のため、ここでの解析と書式設定方法のコードがあります「DataValueは」プロパティにデータ:

public class DataCheckBox : CheckBox { 
    public virtual object DataValue { 
     get { return this.Checked; } 
     set { 
      if (value == null || value is DBNull) { 
       this.CheckState = CheckState.Indeterminate; 
      } 
      else { 
       this.Checked = (bool)value; 
      } 
     } 
    } 
} 
+0

さて、それは巧妙なものです... – Mac

+0

CheckBoxは、実証済みのように、nullable(DBNull)カラムへのデータバインディングをサポートしているので、賢明ですが実際には必要ありません。 –

関連する問題