vendredi 28 octobre 2016

EF: Databinding checkbox to nullable int value

I am wondering if there is a way of handling nullable values of type int when binding to a CheckBox in Winforms.

Take the following example class:

public class TestClass
{
    public Nullable<int> NULLABLE_INT_VALUE { get; set; }
    public int NON_NULLABLE_VALUE { get; set; }
}

I have a component which inherits from the standard checkbox and allows you to pass an object (i.e. the class instance) and a property name and will set a DataBinding against the checkbox:

public void FSetDataBinding(object BindingObject, string FieldName)
{
    Binding ControlBinding = new Binding("Checked", BindingObject, FieldName) { NullValue = false };
    ControlBinding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
    ControlBinding.Format += (s, e) => { e.Value = e.Value.ToString() == "1"; };
    ControlBinding.Parse += FormDBCheckBox_Parse;
    DataBindings.Add(ControlBinding);
}

private void FormDBCheckBox_Parse(object sender, ConvertEventArgs e)
{
    if((bool)(e.Value))
    {
        e.Value = "1";
    }
    else
    {
        e.Value = "0";
    }
}

If I create two checkbox controls (chkNullableValue and chkNonNullableValue respectively), I can bind them to a TestClass (we're assuming here that TestClass is an EF version of the database table:

TestClass IAmATest = new TestClass() { NULLABLE_INT_VALUE = 1, NON_NULLABLE_VALUE = 0 }
chkNullableValue.FSetDataBinding(IAmATest, "NULLABLE_INT_VALUE");
chkNonNullableValue.FSetDataBinding(IAmATest, "NON_NULLABLE_VALUE");

Both properties are from the same object and are bound in exactly the same way; however, when I try and check the box which is bound to the nullable value, for some reason the (set;) accessor is never hit against the property. What happens is that, on the form, the box appears to be checked; however, since the underlying property against the box has not been updated, the next time it formats the control for display, e.Value is still "0" and the box will 'un-check' itself. This also means that calling SaveChanges() doesn't update the value, as it has technically never been updated.

It's also important to note here: Yes, it's true that NullValue = false against the Binding that is created; however, in this specific case, the nullable value already has a value of "0" and so will never actually be null (but it could be in other cases).

The opposite is true for the non-nullable property and this behaves exactly as I would expect; when you check the box on the form, the value of NON_NULLABLE_VALUE is updated and set to "1" as part of FormDBCheckBox_Parse, so the next time the control formats itself, ControlBinding.Format returns "true" and the checked property is set accordingly.

As I'm of the opinion that if something is a flag (and therefore either 'off' or 'on' at all times) then null values shouldn't be allowed against the field in the database and so in the end I just made the value non-nullable; however, I want to understand exactly why I had so much trouble using the nullable type in case I need to use it in future for anything else.




Aucun commentaire:

Enregistrer un commentaire