Data Binding with a Custom UserControl’s Text Property

Update: Found a better solution than originally posted

We ran across this vexing problem at work today. It took a while to find the ultimate solution.

We are using VB.NET 2005 to develop a new module for our business application. A prototype had been used to test some of the built-in features, including data binding. Data binding seemed to work just fine when bound to our CSLA.NET-based objects.
For production, of course, we wanted some custom composite controls. For example, we need a date text box that consists of a label, a textbox, and a button that launches a calendar dialog. When we made this fairly simple composite control, the data binding didn’t work when the control was validated.

Google searches only pointed out that other people have had the same problem and resolved it by changing the property name from Text to something else, like TextData. We tried that, and data binding worked again without having to do anything special within the control.

This workaround was not satisfactory. Why should programmers who have become used to consistently using the Text property on controls have to remember to use a different property name?

Some further research led us to the MSDN article How to: Apply the PropertyNameChanged Pattern. The problem with this article is that it deals with a user control that handles complex data binding. We only needed simple binding.

More searching got us to the Walkthrough: Creating a User Control that Supports Simple Data Binding article. This article didn’t work for us for two reasons. First, the property used was not Text. We already knew that a different property name would work. We wanted the Text property to work. The other problem was that this walkthrough is designed to work with drag-and-droppable data sources. CSLA.NET objects are not bound with drag-and-drop operations.

During some more research, we ran across a newsgroup thread that mentioned the UserControl object does some special overriding of the Text property. Not only does it disable data binding, the property is not browsable in the designer. Sure enough, the UserControl.Text property defines <BindableAttribute(False)>, which disables data binding. We tried adding the <Bindable(True)> attribute to our property, but it didn’t help.

Finally, while reading the Change Notification in Windows Forms Data Binding topic for the umpteenth time, we ran across the statement, “Finally, from the control side you must expose a PropertyNameChanged event for each property designed to be bound to data.” We hadn’t needed that before, but we thought, let’s give it a try.

We tried adding the following line to the control class:

Public Event TextChanged As EventHandler

This gave us the ubiquitous squiggly indicating a problem. It turns out that the Control class already defines this event. The problem is that data binding needs to get this event to know that it is appropriate to pull the value from the control into the data source. The Control.TextChanged documentation suggests viewing the OnTextChanged method.

So, OnTextChanged will raise the event, but where should we put it? In our case, we don’t want the text going to the datasource until the control has been validated. Databinding happens during the Validating event, so we added the following line the Validating event of the user control (within the user control):

OnTextChanged(New System.EventArgs)

This took care of the problem, and we were able to move on to the next hurdle.

Advertisements
  1. #1 by Mike on January 2, 2009 - 5:15 pm

    Good blog. Ran into this exact same problem and your advice pointed me in the right direction. here’s the C# that fixed it. Do a google on implementing INotifyPropertyChanged.

    Assume a UserControl with a single TextBox for simplicty.

    [System.ComponentModel.DefaultBindingProperty(“Text”)]
    public partial class MinMaxTextBox : UserControl, INotifyPropertyChanged
    {

    [Bindable(true)]
    public override string Text
    {
    get { return txtData.Text; }
    set { txtData.Text = value; }
    }

    private void txtData_TextChanged(object sender, EventArgs e)
    {
    if (TextChanged != null)
    {
    TextChanged(sender, e);
    }
    PropertyChanged(this, new PropertyChangedEventArgs(“Text”));
    }
    }

  2. #2 by Yev on February 3, 2009 - 4:15 pm

    Mike, in your response, what is TextChanged? an event of the usercontrol? How is it wired?

  3. #3 by Lior on February 21, 2009 - 8:32 pm

    I got a form with a user-control and a toolbar with a button. when I click the button i commit the changes to the database.
    The problem is that the “TextChanged” event is fire after saving changes. When I change the property name from “Text” to something else, everything works fine. any idea?

  4. #4 by Lior on February 21, 2009 - 8:35 pm

    … this means that this solution is doing something different from the default behaviour

  5. #5 by hurcane on February 22, 2009 - 4:24 pm

    Lior,

    I can’t provide a specific answer to your problem. However, you can put a breakpoint on the OnTextChanged line in your code to see the call stack that leads to it.

    I can make a wild guess, though. I suggested putting OnTextChanged in the Validating event because that worked for our needs. I know that the Validation events can do some strange things when a MenuStrip or ToolStrip control is involved.

  6. #6 by PavlinII on October 14, 2009 - 4:34 am

    Great article! I wish I found it last night đŸ™‚

    I’ve came across the same issue last night and tried almost everything else except checking OnTextChanged procedure.

    Thanks!

  7. #7 by Ravenheart on April 25, 2014 - 4:53 am

    The problem I had was that I already had an EventHandler PropertyNameChanged; declared for external usage and that was breaking the databind.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: