Browse DevX
Sign up for e-mail newsletters from DevX


The Baker's Dozen: 13 Productivity Tips for Building a .NET Distributed Application : Page 5

The Common Ground Framework for .NET provides a set of starter classes for building database applications in a distributed environment.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Tip 9: A Generic Solution for Data Binding
cgsControls also offers capabilities to simplify data binding. Some developers have difficulty implementing data binding across different controls. Data binding for a TextBox differs from a ComboBox, and for a CheckBox. Another challenge is that data binding sometimes requires a measurable amount of code.

The CG Framework simplifies this through a binding interface.

public interface IBoundControl { void BindControl(); }

Once again, here is where interfaces become valuable. As I discussed in prior tips, an interface is an agreement—that any class/control that implements the interface will contain a specific set of functions. In the case above, all the subclassed controls in the cgsControls class will implement the public interface IboundControl.

public class cgsComboBox : System.Windows.Forms.ComboBox , IBoundControl public class cgsTextBox : System.Windows.Forms.TextBox , IBoundControl public class cgsDateTime : System.Windows.Forms.DateTimePicker, IBoundControl public class cgsCheckBox : System.Windows.Forms.CheckBox, IBoundControl

The next step is to add some properties to each control that implement the IBoundControl interface. These properties will define the table and column to which each control will data bind. Most controls (CheckBox, TextBox, DateTimePicker) require only two properties, one for the data table and one for the data column.

private DataTable _DtSource; public DataTable DtSource { get {return _DtSource ;} set {_DtSource = value; } } private DataColumn _DcSource; public DataColumn DcSource { get {return _DcSource ;} set {_DcSource = value; } }

The ComboBox, however, requires additional properties to display values from a foreign table:

  • An additional data table property if the ComboBox displays descriptions from a foreign table (DtForeignTable, which becomes the ComboBox's data source)
  • A data column property for the column being displayed (DcDisplayMember, as DisplayMember)
  • A data column property for the column from the foreign table that maps to the actual data column source (DcValueMember, as ValueMember).
In many cases, DcValueMember and DcSource will be the same (e.g. a classcode in a Child table may also be called classcode in the parent description table), but that may not always be the case. The database schema may use 'PK' and 'FK' conventions, thus the support for two properties.

Next, controls that implement the IBoundControl interface must contain a function called BindControl. Here is one of the great beauties of interfaces: the BindControl function for each control can be different, based on the type of control. This is critical because each control is bound differently. The TextBox and DateTimePicker controls are bound as follows.

public void BindControl() { if(this._DcSource != null && this._DtSource != null) { this.DataBindings.Clear(); this.DataBindings.Add("Text", this._DtSource, this._DcSource); } }

The BindControl function for the checkbox differs because the binding applies to the checked property, not the text property. The checked property returns a Boolean that can be bound to a corresponding Boolean data type. The function for the ComboBox control also differs because the function must set the additional properties for the foreign table, and the display/value member.

In addition, the TextBox class in cgsControls also contains code to display currency/decimal data in the correct format.

So the final question you may be asking is: "OK, so I've set binding properties... What calls the BindControl function?" If all data-bound controls reside on a common entry container or form, you could, as one option, place the following code in the common form.

protected virtual void UpdateBindings() { // 1) loop through each control // 2) if the control implements the interface, // 3) call the control's BindControl function foreach(Control oControl in this.Controls) if(oControl is cgsControls.IBoundControl) ((cgsControls.IBoundControl)oControl). BindControl(); }

Tip 10: Integrating Filter Capabilities with Data Maintenance Functions
The application must allow users to retrieve a list of data according to runtime criteria (such as jobs entered/updated between two dates, jobs for a set of customers, jobs exceeding a dollar threshold). You must develop a user-friendly interface screen for users to make filter selections and present the results in a screen that users may view, navigate through, print to Excel, etc. This tip presents a generic form class and form class manager for data maintenance functions.

Figure 4: Example of data maintenance screen.
The CG Framework contains a base data maintenance form named cgsFrmDataMaintenance in the cgs.Winforms namespace. You can use this form to automate many instances where users look up data by criteria on the first screen (see Figure 4), view result sets on the second screen, add/edit/delete data on the third screen, and even view the history of changes to data (see Tip 13 for more on viewing audit trail data). The result set portion integrates the DataGrid that I presented in the November/December 2004 issue of CoDe Magazine. I've enhanced the DataGrid so that you can export the contents to Excel. The data maintenance screen utilizes the data binding in the previous tip.

The data maintenance form contains buttons for selection criteria, viewing result sets, and adding/editing data. A developer can design containers (user controls) to drop onto this form: the form manages the display of each container by looking for containers that implement one of three different interfaces (ICriteriaContainer, IResultContainer, and IEntryContainer). To simplify the creation of new containers to meet your data maintenance needs, the CG Framework supplies three base containers in cgs.Winforms.Containers that implement each of these interfaces (cgsContainerCriteria, cgsContainerResult, and cgsContainerEntry).

Figure 4 shows a basic example of the maintenance form. The active criteria panel displays a very simple criteria screen. The developer can design any criteria container, inheriting from cgsContainerEntry. The interface contains a function called GetCriteria, which you can override to read the criteria selections. The developer can then design a results screen that inherits from cgsContainerResult, using the function ShowCriteriaResults. Finally, the developer can design a data entry/update container that inherits from cgsContainerEntry, using the function ShowDetailData. An application could contain several maintenance forms, all using the same general mechanics and all containing the same look and feel.
Many functions in the Common Ground Framework are defined as virtual-allowing a developer to extend or override.
This type of consistency greatly helps users.

The criteria, results, and data buttons automatically look for containers on the form that implement the corresponding interfaces. Because of this, all a developer needs to do is define each of the three specific containers, drop them on an instance of a maintenance form based on cgsFrmDataMaintenance, and run the form. Once again, the power of interfaces!

Again, the base maintenance form contains stub virtual functions for each button: this allows you to implement your own code for retrieving result sets, adding data, and so on. The Word document in the zip download contains a list of all methods you can tap into.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date