Windows Forms databinding has greatly improved in .NET 2.0. Microsoft has enhanced our object-oriented toolbox by allowing Windows Forms controls to databind to our custom objects' properties. This new functionality is centered around the new
BindingSource component. Although this component takes a lot of the leg-work out of databinding custom objects, I recently had an issue with some rather large objects that contained both
ReadOnly properties. After setting up databinding, I had to go through and manually set the "
Enabled" property of these controls depending on whether each individual property was
ReadOnly or not. I decided to create a custom
BindingSource component that would take care of this manual process in the background.
Another option that I considered exploring was creating a custom attribute to add to the properties that I wanted to have
Read-Write capabilities to. The reason I didn't do this was that I wanted to avoid requiring the business object developer having to implement more than what is necessary just to satisfy the UI developer.
Using the code
We start off by creating a class library that will contain our custom
SmartPropertyBindingSource component and our
ReadOnlyBehavior enumeration. This enumeration will be used to determine the rendering behavior of the databound control. This class library project should reference the
System.Windows.Forms and set it to be a globally imported namespace (you may also just write
Imports System.Windows.Forms at the top of the SmartPropertyBindingSource.vb file).
We will be supporting two options for how the databound control of the
ReadOnly property will be rendered on the form. This is set through the
ReadOnlyControlBehavior property in the
SmartPropertyBindingSource. You can choose to have it disabled or hidden.
Public Enum ReadOnlyBehavior
Disable = 0
Hide = 1
We will now add a class named
SmartPropertyBindingSource which inherits from
Public Class SmartPropertyBindingSource
Next, we will create a
Public property in this class to set the control rendering behavior for
Public Property ReadOnlyControlBehavior() As ReadOnlyBehavior
Set(ByVal value As ReadOnlyBehavior)
mReadOnlyBehavior = value
We will also go ahead and provide overloads for the three constructors in the base class. Once we have done this, we are ready to write the functionality of the class. By overriding the
OnBindingComplete, we will have access to the current object's property information, thanks to the
System.Reflection namespace. With this information, we will be able to find out if the property in question is
Protected Overrides Sub OnBindingComplete(ByVal e As _
Dim t As Type = e.Binding.BindingManagerBase.Current.GetType
Dim prop As System.Reflection.PropertyInfo = _
If Not prop.CanWrite Then
Select Case Me.ReadOnlyControlBehavior
e.Binding.Control.Enabled = False
e.Binding.Control.Visible = False
That's all there is to it. Using reflection, we can investigate whether the property is
ReadOnly and render (or not render) the control appropriately. We also don't have to ask the domain object's developer to do anything special to improve the user experience.
Points of Interest
The new .NET 2.0 framework provides a great deal of enhanced functionality from the previous framework allowing for easier integration of custom business objects. We can build upon this functionality by customizing classes to better suit our needs.