24

I'm currently using winforms databinding to wire up a data editing form. I'm using the netTiers framework through CodeSmith to generate my data objects. For database fields that allow nulls it creates nullable types. I've found that using winforms databinding the controls won't bind properly to nullable types.

I've seen solutions online suggesting that people create new textbox classes that can handle the nullable types but that could be a pain having to swap out the textboxes on the forms I've already created.

Initially I thought it would be great to use an extension method to do it. Basically creating an extension property for the textbox class and bind to that. From my limited extension method experience and doing a bit of checking online it looks like you can't do an extension property. As far as I can tell, binding has to be through a property since it needs to be able to get or set the value so an extension method wouldn't work.

I'd love to find a clean way to retrofit these forms using something like extension methods but if I have to create new textbox and combo box controls that's what I'll do.

My project is currently limited to .Net 2.0 due to the requirement to run on Windows 2000.

Any suggestions?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Steve Hiner
  • 2,523
  • 3
  • 24
  • 33

4 Answers4

53

In the comments section of the article referenced above one of the posters comes up with a simple solution.

Instead of binding with:

textBox1.DataBindings.Add("Text", myClass, "MyTextProperty");

Bind with:

textBox1.DataBindings.Add("Text", myClass, "MyTextProperty", true, DataSourceUpdateMode.OnPropertyChanged, string.Empty); 
shindigo
  • 1,267
  • 15
  • 29
  • 3
    Bless you heart! Seriously! I've been wrestling with this for HOURS! :-) – HumbleBeginnings Nov 20 '18 at 04:55
  • 1
    This works around binding to nullable types by replacing the null value with something else. It doesn't solve binding to nullable types if you explicitly want null values to be saved to the nullable value bound to. There's an "empty value" for string, but not so much for most other types. – Kissaki May 17 '19 at 07:31
  • @Kissaki, the parameter string.Empty indicates that when textBox1.Text property has empty string value, the value stored in "MyTextProperty" will be null. – David Con Mar 26 '21 at 14:43
6

I've just stumbled across this problem myself and it's a real headache.

The funny thing about binding nullable types is that a DataGridView handles them without any problems - it's just the text boxes that cause problems.

It's pretty nasty - it even seems to prevent closing a form when you have an empty value in the text box and it appears that you can't tab away from it either.

So, it's not a great answer but my suggestion is to try to stick to datagridviews for the nullable types on a form.

Another suggestion is to use an 'extender provider' as suggested here though I haven't tested it yet:

EDIT: Have now downloaded the sample code on this page and it works BRILLIANTLY.

http://www.thejoyofcode.com/Databinding_and_Nullable_types_in_WinForms.NET.aspx

Damien
  • 1,463
  • 1
  • 18
  • 30
2

Ooh, nasty... I can only think of a couple of ways to achieve this and neither of them are what I would call ideal.

  • The first is to write a wrapper for your data object that contains nullables that converts all the nullables to empty strings. Bind to your wrapper object.

  • The second is to make sure that all the values in your database are not null... again, not ideal

  • The third you've already decided isn't viable in this situation is that you create a custom object that extends the textbox to add a property that can bind to a nullable.

  • The fourth most ideal way I could think of doesn't appear to be possible. Create an extension property which would allow you to extend all textbox objects and bind to that - but it doesn't appear that extension properties are possible at this time. It does seem like this is a situation where this type of feature would be particularly useful in the .NET framework.

BenAlabaster
  • 39,070
  • 21
  • 110
  • 151
0

From Databinding and Nullable types in WinForms.NET

Scenario

  • You have an Entity Type with a Nullable property.
  • You have a TextBox which is bound to that property.
  • When the user clears the text in the TextBox, you want the value of your property to be set to null.

Problem

The result of the databinding will simply not succeed when clearing a TextBox which is bound to a Nullable type.

Solution

In this article I am going to show how you can do this by using an Extender Provider.

Simply add a Component class to your project which also implements the IExtenderProvider interface

[ProvideProperty("NullableBinding", typeof(TextBox))]  
public partial class NullableExtender : Component, IExtenderProvider

The ProviderProperty attribute indicates that when adding the NullableExtender component to your Form or UserControl, all the TextBoxes will have an additional property named NullableBinding. It will look something like this in the VS.NET designer:

NullableBinding Property

Now to implement some functionality for this property:

private Dictionary<Control, Boolean> _nullables = new Dictionary<Control,bool>();

/// <summary>
/// This is the get part of the extender property.
/// It is actually a method because it takes the control.
/// </summary>
/// <param name="control"></param>
[DefaultValue(false),
Category("Data")]
public bool GetNullableBinding(Control control)
{
    bool nullableBinding = false;
    _nullables.TryGetValue(control, out nullableBinding);
    return nullableBinding;
}

/// <summary>
/// This is the set part of the extender property.
/// It is actually a method because it takes the control.
/// </summary>
/// <param name="control"></param>
/// <param name="nullable"></param>
public void SetNullableBinding(Control control, bool nullable)
{
    if (_nullables.ContainsKey(control))
        _nullables[control] = nullable;
    else
        _nullables.Add(control, nullable);
    if (nullable)
    {
        // Add a parse event handler.
        control.DataBindings["Text"].Parse += new ConvertEventHandler(NullableExtender_Parse);
    }
}

/// <summary>
/// When parsing, set the value to null if the value is empty.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void NullableExtender_Parse(object sender, ConvertEventArgs e)
{
    if (e.Value.ToString().Length == 0)
    {
        e.Value = null;
    }
}

The code that actually does the trick above is adding the event handler for the databinding Parse event. The event handler simply sets the value to null if the value is an empty string, and the databinding succeeds.

The default value of the property is set to false since most properties are not of a Nullable type, and I would suggest not setting the NullableBinding to true for these properties... ;)

Community
  • 1
  • 1
Stécy
  • 11,951
  • 16
  • 64
  • 89