Ivan-Mark Debono
Ivan-Mark Debono

Reputation: 16310

How to use a lambda expression to update a property?

I have the following class:

public class MyClass
{
    public int? Field1 { get; set; }
    public int? Field2 { get; set; }
}

The textbox controls on the form are bound to an instance of this class through a BindingSource, and the data source is update on the OnValidated event.

However, when the textbox is empty, the property it's bound to is not being updated (the previous value is being displayed again):

So, on the controls' OnValidating event I added the following:

int value;
bool ok = int.TryParse(((TextBox)sender).Text, out value);
if (!ok)
{
    myClassInstance.Field1 = null;
}

Questions:

  1. Is the above the normal behavior of the BindingSource when the value of the TextBox is empty?

  2. Is it possible to have a generic method that I can call in my OnValidating events. Something like:

    OnValidatingMethod((TextBox)sender, x => x.Field1);
    

The above line of code obviously doesn't work because the object instance is not referenced. But I was wondering if something like that is possible? Maybe an extension to the class:

myClassInstance.SetProperty(((TextBox)sender).Text, x => x.Field1);

Upvotes: 2

Views: 1106

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205629

The whole idea of data binding is to abstract the target from the source. If you create such event handlers, the abstraction is over.

What you see is not normal of course, but is result of a very old bugs kept for "backward compatibility". It has been fixed long time ago by adding additional properties to the Binding class, but again for backward compatibility the default values are set to mimic the old behavior.

The properties that you need to set to make it work as expected are FormattingEnabled to true, and NullValue to "". I usually use one of the DataBindings.Add or Binding constructor overloads that allows specifying all that information, like this:

textBox.DataBindings.Add("Text", bs, "Field1", true, DataSourceUpdateMode.OnValidation, "");

Here is a full demo:

using System;
using System.Windows.Forms;

namespace Samples
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var form = new Form();
            var textBox1 = new TextBox { Parent = form, Left = 16, Top = 16 };
            var textBox2 = new TextBox { Parent = form, Left = 16, Top = textBox1.Bottom + 16 };
            var bs = new BindingSource { DataSource = typeof(MyClass) };
            textBox1.DataBindings.Add("Text", bs, "Field1", true, DataSourceUpdateMode.OnValidation, "");
            textBox2.DataBindings.Add("Text", bs, "Field2", true, DataSourceUpdateMode.OnValidation, "");
            bs.DataSource = new MyClass { Field1 = 1, Field2 = 2 };
            Application.Run(form);
        }
    }

    public class MyClass
    {
        public int? Field1 { get; set; }
        public int? Field2 { get; set; }
    }
}

Finally, if you really want to be involved in the parsing part, you should attach handler to Binding.Parse event.

Upvotes: 1

Related Questions