views:

1398

answers:

2

In Windows Forms (.NET 2.0, Visual Studio 2005 SP1) : I have a typed DataSet, with a column which type is System.Boolean, which is nullable and which default value is DBNull. I have a Form, containing a CheckBox control that I want to bind to the prior column value.

  • I have tried to bind the Checked property to the column via the designer : it works great, only if the default value for the column is set to either True or False.
  • I have tried to bind the CheckState property to the column via the designer, and attaching my own Format and Parse event handlers but they never get called :

    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
    };
    
  • I have tried to create a custom Binding instance in the code, attach my event handlers and add it to the CheckBox bindings : the event handlers are still never get called...

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

As a note : a DBNull value is acceptable only when coming from the DataSet (it means the value has never been set). But the user should only be able to set the value to True or False via the CheckBox.

For reference, here is the code of the parsing and formatting methods :

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;
}
+1  A: 

The easist way I know, is derive from CheckBox class, add "DataValue" property which can handle DBNull values and bind the data to "DataValue" property:

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;
   }
  }
 }
}
TcKs
Well, that's a clever one...
Mac
Clever but not really needed since CheckBox supports data binding to nullable (DBNull) columns as I demonstrated.
Alfred Myers
+2  A: 
Alfred Myers
I think it would hurt my head (a lot) to bind a boolean data to an enumerated type (with 3 possible values !), but I will try it anyway out of curiosity...
Mac
I tried on Visual Studio 2005 and it worked too.Both via the designer and via code.
Alfred Myers
Your sample works, but is not correct for this question. @Mac want "DBNull can be populated from row to control but CAN NOT be populated from control to row". The databinding between "MyColumn" and "CheckState" does not achieve it. For correct behaviour you need hook the Format/Parse event and edit the passing value. - if is scenario as @Max wrote frequent it's better use some reusable solution.
TcKs
I think you guys need to cool off a bit... @Alfred Myers : thanks for your answer. I would not use it because of personal taste (looks too much of a hack for me), but I will certainly learn many things when I discover why it works (when I thought it should not).
Mac
@TcKs: He specifically states that is is not going to allow the user to set the value to DBNull from the control: "a DBNull value is acceptable only when coming from the DataSet (it means the value has never been set). But the user should only be able to set the value to True or False via the CheckBox."
Alfred Myers
Now you're talking : this is indeed a hidden feature.
Mac