New Posts New Posts RSS Feed: Tech Tip: Refactoring Your User Interface with DataConverters and ViewDescriptors
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Tech Tip: Refactoring Your User Interface with DataConverters and ViewDescriptors

 Post Reply Post Reply
Author
IdeaBlade View Drop Down
Moderator Group
Moderator Group
Avatar

Joined: 30-May-2007
Location: United States
Posts: 353
Post Options Post Options   Quote IdeaBlade Quote  Post ReplyReply Direct Link To This Post Topic: Tech Tip: Refactoring Your User Interface with DataConverters and ViewDescriptors
    Posted: 06-Jun-2007 at 2:44pm

Level 200
DevForce Express

July 19, 2006

DevForce databindings always use a DevForce object called a DataConverter, which describes how the control being bound to a particular piece of data should behave with respect to that data. If you use a DevForce BindingManager (such as the ControlBindingManager) to populate your form with controls and to configure databindings, it will assign a particular flavor of DataConverter called a DefaultConverter for use with each binding. You can happily leave everything to the designer; but there is unused power under the hood of those DevForce databindings, much of it housed in the DataConverters and in another closely related object called a ViewDescriptor. In this Tech Tip you’ll get a glimpse of that power so you’ll know where to look when you need it.

A DevForce ControlBindingManager only exposes one property of the DefaultConverter through the designer, that being the Editabilty of the target control which can be set to Disabled, ReadOnly, Optional, or Required. (In code, there are additional behaviors you can control, but we’ll leave those for another Tech Tip.)

Suppose you drag a DateTime property into the ControlBindingManager’s design grid, and then give the designer the OK to generate code to populate your form and set up databindings. The code it generates lands, according to prescribed Visual Studio practice, in the designer code file associated with the form. If you named your form “EmployeeForm”, for example, the code will be written into a file named EmployeeForm.Designer.vb (or “.cs” if you’re working in C#).

The code for the binding looks like the following:

 C#:

this.mEmployeesCBM.Descriptors.Add(
  new
IdeaBlade.UI.WinForms.ControlBindingDescriptor(
  this.mBirthDateDateTimePicker, typeof
(Model.Employee),
  "BirthDate"));

VB.NET:

Me.mEmployeesCBM.Descriptors.Add( _
  New
IdeaBlade.UI.WinForms.ControlBindingDescriptor( _
  Me.mBirthDateDateTimePicker, GetType
(Model.Employee), _
  "BirthDate"))

In the above statement, an overload of the Add() method of the ControlBindingManager’s Descriptors collection has been invoked with three parameters: the target control, the type of the business object being bound, and the name of the property on that object which is to be bound to the specified control. There is no mention of a DataConverter, but that’s only because the DefaultConverter is being used. Other overloads of Add() permit you to specify the DataConverter explicitly.

There are other types of DataConverter besides the DefaultConverter that you can assign to a binding. If the bound property is a String, you can assign a TextConverter or RegexConverter, each having its own special settable properties. If the bound property is a number, you can assign a NumericConverter or NumericRangeConverter. If it’s a DateTime, you can assign a DateConverter or DateRangeConverter; and so on.

Suppose you decide to use a more sophisticated DataConverter in your Employee.BirthDate databinding; let’s say, a DateRangeConverter. In the ControlBindingManager designer, you so indicate by changing the setting using the dropdown list in the Data Converter column. You then click the builder button to its immediate right to explore the properties available for configuration through the designer for this type of DataConverter. You find that you can, in addition to controlling the Editability of the control, specify a FormatString to determine how it is displayed; and also specify minimum and maximum acceptable date values through the MinDate and MaxDate properties. You are, however, limited (in the designer only) to hard-coded date values for the latter.

You establish settings for these properties of the DateRangeConverter, then click OK in the ControlBindingManager designer to indicate that you want it to generate code to populate your form and set up the databindings. This time the code for the BirthDate property binding looks like the following:

C#:

this.mEmployeesCBM.Descriptors.Add(
  new
IdeaBlade.UI.WinForms.ControlBindingDescriptor(
  this.mBirthDateDateTimePicker, typeof
(Model.Employee),
  "BirthDate", DateRangeConverter1));

VB.NET:

Me.mEmployeesCBM.Descriptors.Add( _
  New
IdeaBlade.UI.WinForms.ControlBindingDescriptor( _
  Me.mBirthDateDateTimePicker, GetType
(Model.Employee), _
  "BirthDate", DateRangeConverter1))

Notice that this overload of the Add() method includes a fourth argument, to which we have passed the parameter DateRangeConverter1. We’ll also find additional code that configures the DateRangeConverter1 DataConverter:

C#:

DateRangeConverter1.MaxDate =
  new
System.DateTime(2099, 12, 31, 0, 0, 0, 0);
DateRangeConverter1.MinDate =
  new System.DateTime(1900, 1, 1, 0, 0, 0, 0);

VB.NET:

DateRangeConverter1.MaxDate = New Date(2099, 12, 31, 0, 0, 0, 0)
DateRangeConverter1.MinDate =
New Date(1900, 1, 1, 0, 0, 0, 0)

We do not have a statement to set the value of the FormatString property, but that again is simply because we left it at its default setting of “d” in the designer. Statements elsewhere in the designer code file declare and instantiate DateRangeConverter1.

Now, this DateRangeConverter is an interesting artifact. It is designed to apply specifically to a databinding involving DateTime types, but it is not specific to the Employee.BirthDate property, or any property. That means it can be defined centrally and reused across many databindings involving many different properties and many different controls. If, for example, we want all dates in our application to be formatted with the FormatString “d” and restricted to dates in the 20th and 21st centuries, we can reuse this DateRangeConverter across all of them. Instead of hard-coding the limit dates in the statements that assign them above, we can set them to variables whose values can be changed by a developer, administrator or end user, as desired.

ViewDescriptors

Another overload of the Descriptors collection's Add() method permits us to take things in still another direction.

C#:

public IdeaBlade.UI.WinForms.ControlBindingDescriptor Add(
        System.Windows.Forms.Control pControl,
        IdeaBlade.UI.ViewDescriptor pViewDescriptor)

VB.NET:

Public Function Add(ByVal pControl As System.Windows.Forms.Control,
        ByVal pViewDescriptor As IdeaBlade.UI.ViewDescriptor)
        As IdeaBlade.UI.WinForms.ControlBindingDescriptor

This overload takes only two arguments: (1) a UI control (as before); and (2) something called a ViewDescriptor.

What is a ViewDescriptor? Simply a DevForce class that nails the specifications encapsulated in a DataConverter to a specific property of a specific business object. In other words, it says, “When you use this particular property in a databinding, make that databinding behave as this particular DataConverter says it should.” Here’s what this looks like in code:

C#:

private IdeaBlade.UI.DateRangeConverter
  mStandardDateRangeConverter;
private
IdeaBlade.UI.ViewDescriptor
  mEmployeeBirthDateViewDescriptor;

mStandardDateRangeConverter =
  new
IdeaBlade.UI.DateRangeConverter(
  IdeaBlade.UI.Editability.Optional);
mStandardDateRangeConverter.MaxDate =
  new
System.DateTime(2049, 12, 31, 0, 0, 0, 0);
mStandardDateRangeConverter.MinDate =
  new System.DateTime(1900, 1, 1, 0, 0, 0, 0);

mEmployeeBirthDateViewDescriptor =
  
new IdeaBlade.UI.ViewDescriptor(typeof
(Employee),
  "BirthDate", mStandardDateRangeConverter);

this.mEmployeesCBM.Descriptors.Add(
  new IdeaBlade.UI.WinForms.ControlBindingDescriptor(
  this
.mBirthDateDateTimePicker,
  EmployeeBirthDateViewDescriptor));

VB.NET:

Private mStandardDateRangeConverter As _
  IdeaBlade.UI.DateRangeConverter
Private mEmployeeBirthDateViewDescriptor As
_
  IdeaBlade.UI.ViewDescriptor

mStandardDateRangeConverter = _
  
New
IdeaBlade.UI.DateRangeConverter( _
  IdeaBlade.UI.Editability.[Optional])
mStandardDateRangeConverter.MaxDate = _
  
New Date
(2049, 12, 31, 0, 0, 0, 0)
mStandardDateRangeConverter.MinDate = _
  
New Date(1900, 1, 1, 0, 0, 0, 0)

mEmployeeBirthDateViewDescriptor = _
  
New IdeaBlade.UI.ViewDescriptor(GetType
(Employee), _
  
"BirthDate", mStandardDateRangeConverter)

Me.mEmployeesCBM.Descriptors.Add( _
  New
IdeaBlade.UI.WinForms.ControlBindingDescriptor( _
  Me.mBirthDateDateTimePicker, mEmployeeBirthDateViewDescriptor))

You now have the means of centralizing the specifications for the UI behavior of any given property of any given business object. Having once defined the specifications, you can reuse them as often as needed when displaying that property in different contexts: on different tabs within a single form, on different forms, in different user controls, in loose controls and in grids, and so forth. You can, if you wish, create a central library of ViewDescriptors to define the UI behavior specs for every property in your business model!

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down