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):
This took care of the problem, and we were able to move on to the next hurdle.