Best way to databind a Winforms control to a nullable type?
Asked Answered
L

5

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?

Libretto answered 17/12, 2008 at 22:55 Comment(0)
S
55

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); 
Sandoval answered 19/8, 2010 at 17:53 Comment(3)
Bless you heart! Seriously! I've been wrestling with this for HOURS! :-)Rehearse
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.Fortson
@Kissaki, the parameter string.Empty indicates that when textBox1.Text property has empty string value, the value stored in "MyTextProperty" will be null.Bluecoat
P
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

Prophecy answered 5/2, 2009 at 4:29 Comment(0)
B
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.

Bassorilievo answered 18/12, 2008 at 2:29 Comment(0)
L
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... ;)

Libation answered 27/12, 2018 at 13:12 Comment(0)
V
0

You can use my library WinForms.NullableBinding

Features

Strongly Typed Expressions: Avoid the risk of typos in your data binding expressions and gain the benefits of compile-time checks and IntelliSense autocompletion in your IDE.

Nullable Data Binding: This library supports standard data binding, but more importantly, it allows for null values to be assigned to and retrieved from the bound data member.

Usage Example Traditional approach to adding a data binding:

txtTotal.DataBindings.Add(nameof(txtTotal.Text), _bindingSource, nameof(_transaction.Total), true, DataSourceUpdateMode.OnPropertyChanged);

With WinForms.NullableBinding, you can add a data binding in a strongly typed and potentially nullable way:

using WinForms.NullableBinding;

var obj = new Order
{
  Code = "OrderCode",
  Total = 100.00
};

var bindingSource = new BindingSourceGeneric<Order>(obj);

txtTotal.AddDataBinding(bindingSource, a => a.Total);

How to Use

Simply include the provided extension methods in your project, and make sure to import the corresponding namespace in your code files. You can then use the AddDataBinding and AddNullableDataBinding extension methods for data binding in place of traditional string-based methods.

Vc answered 16/11, 2023 at 4:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.