Introduction
One common task for web applications is to maintain data. This means to insert, update, delete, and display data. Both .NET 1.x and 2.0 have web controls that you can use to do this task. DataGrid
, DataList
, GridView
, and DetailsView
are some of the web controls that you can use to maintain data. In this article, you will see how to create a custom web control that will help you to maintain data. It is assumed that you already know how to create web controls, so we will focus our attention on the main points of our web control. You can download the code for the implementation details (Important: read the readme.txt file for installation details).
DataCatalog control overview
The DataCatalog
web control allows you to display data. You can update or delete a data record by selecting it and then pressing the Update or Delete button, respectively. Click on the Insert button to add a new data record. To order the data, just click a column name, and the data will be ordered based on the selected column.
Figure 1. DataCatalog web control
The table below has a more detailed technical explanation:
Section name |
Description |
Header |
The DataCatalog web control has a header section that contains the names of the data columns from our data source. When the user clicks a column name, the data is ordered by the selected data column. |
Selection column |
At the left of each data record, a radio button is displayed to allow the user to delete or to update the selected data record. |
Data record content |
Below the header section, the content of each data record is displayed. You can use the DataFieldsFormatString property to specify the format (e.g., money format) to a data field value. |
Command section |
This section contains Insert, Update, and Delete buttons. When the Insert button is clicked, the user is redirected to the insert web form. When a data record is selected and the Update button is clicked, the user is redirected to the update web form. When the Delete button is clicked, the selected data record is deleted. |
DataCatalog control properties
The DataCatalog
properties have three main purposes: to specify the SQL statements to select and delete data, to specify the format to be applied to the data field values, and to specify the web forms used to insert, update, and display record details.
Figure 2. DataCatalog properties
The following table contains a description of the DataCatalog
properties:
Property |
Description |
SelectText |
SQL statement used to get the data to be displayed by the DataCatalog web control. |
OrderByColumnSelectText |
SQL statement used to order the data based on the selected data column. |
DeleteText |
SQL statement used to delete the selected data record. |
DbConnectionType |
Used to specify if a SQL client (SQL Server) or OLEDB data provider will be used. |
DataKeyNames |
Data column names used to identify a data record. Specify the data field name(s) used as primary key(s). |
UpdateRedirectUrl |
URL to which the user will be re-directed after clicking the Update button. |
InsertRedirectUrl |
URL to which the user will be re-directed after clicking the Insert button. |
DetailsRedirectUrl |
URL to which the user will be re-directed after selecting a data item. |
DataFieldsFormatString |
String containing the format to be applied to the data fields. For example, the following value is used to give format to date and money data columns, respectively: PURCHASEDATE={0:dd/MM/yyyy}, PRICE={0:c} |
ColumnsStyleString |
String containing the CSS styles to be applied to the columns. |
DataCatalog child controls
The DataCatalog
web control is a composite control. Its control hierarchy is: a Table
object containing three rows. The first row corresponds to the header. The second row corresponds to the data to be displayed. The last row corresponds to the command buttons (Insert, Update, Delete).
Header
The header section is represented by the HeaderItem
object. The HeaderItem
object inherits from the DataCatalogItem
object, which inherits from the TableRow
object.
public class HeaderItem : DataCatalogItem
{
...
}
For each data column, a TableCell
object is added to the header row. Each TableCell
will contain a LinkButton
control that will allow the user to order the data.
protected override void CreateColumnHierarchy(bool useDataSource,
string columnName, bool firstColumn, bool lastColumn)
{
TableCell cell = new TableCell();
base.Cells.Add(cell);
LinkButton link = new LinkButton();
cell.Controls.Add(link);
if (useDataSource)
{
link.Text = columnName;
link.CommandName = "Order";
}
...
}
When the user clicks a LinkButton
, the HeaderItem
bubbles the event to the DataCatalog web control to order the data based on the selected data column.
protected override bool OnBubbleEvent(object source, EventArgs args)
{
CommandEventArgs args1 = args as CommandEventArgs;
if (args1 != null)
{
OrderByCommandEventArgs args2 =
new OrderByCommandEventArgs(source, args1);
base.RaiseBubbleEvent(this, args2);
return true;
}
return false;
}
Body
The body section contains the data. For each data record, a radio button is displayed at the left. At the right, the record data is displayed.
The radio buttons section is represented by the SelectionCell
object. The SelectionCell
object inherits from the TableCell
object.
public class SelectionCell : TableCell
{
...
}
For each data record, a new TableRow
object is added to the selection cell. Each TableRow
will contain a RadioButton
control.
protected override void CreateChildControls()
{
...
for(int i=0; i<this._itemCount; i++)
{
TableRow row = new TableRow();
table.Rows.Add(row);
TableCell cell = new TableCell();
row.Cells.Add(cell);
RadioButton radio = new RadioButton();
cell.Controls.Add(radio);
radio.GroupName = "ItemsGroup";
}
...
}
The record data is represented by the ContentItem
object. The ContentItem
object inherits from the DataCatalogItem
object, which inherits from the TableRow
object.
public class ContentItem : DataCatalogItem
{
...
}
For each data column, a TableCell
object is added to the content row. The first TableCell
will contain a LinkButton
control used to redirect the user to the DetailsRedirectUrl
web form. The next TableCell
objects will contain the data field values.
protected override void CreateColumnHierarchy(bool useDataSource,
string columnName, bool firstColumn, bool lastColumn)
{
...
if (firstColumn)
{
LinkButton link = new LinkButton();
cell.Controls.Add(link);
link.CommandName = "Details";
if (useDataSource)
link.Text = this.GetFieldValue(columnName);
}
else if (useDataSource)
cell.Text = this.GetFieldValue(columnName);
...
}
When the user clicks the LinkButton
in the first cell, the ContentItem
bubbles the event to the DataCatalog
web control to redirect the user to the details web form.
protected override bool OnBubbleEvent(object source, EventArgs args)
{
CommandEventArgs args1 = args as CommandEventArgs;
if (args1 != null)
{
SelectItemEventArgs args2 = new SelectItemEventArgs(source, args1, this);
base.RaiseBubbleEvent(this, args2);
return true;
}
return false;
}
Footer
The footer section is represented by the CommandItem
object. The CommandItem
object inherits from the TableRow
object.
public class CommandItem : TableRow, INamingContainer
{
...
}
The CommandItem
object contains three buttons: Insert, Update, and Delete.
protected override void CreateChildControls()
{
...
Button button = new Button();
cell.Controls.Add(button);
button.CommandName = "Insert";
button.Text = "Insert";
LiteralControl space = new LiteralControl(" ");
cell.Controls.Add(space);
button = new Button();
cell.Controls.Add(button);
button.CommandName = "Update";
button.Text = "Update";
space = new LiteralControl(" ");
cell.Controls.Add(space);
button = new Button();
cell.Controls.Add(button);
button.CommandName = "Delete";
button.Text = "Delete";
}
When the user clicks any button, the CommandItem
bubbles the event to the DataCatalog
web control to redirect the user to the insert or update web form, or to delete the selected data record.
protected override bool OnBubbleEvent(object source, EventArgs args)
{
CommandEventArgs args1 = args as CommandEventArgs;
if (args1 != null)
{
DataOperationCommandEventArgs args2 =
new DataOperationCommandEventArgs(source, args1);
base.RaiseBubbleEvent(this, args2);
return true;
}
return false;
}
DataCatalog web control
The DataCatalog
web control is a composite control. It is composed of the HeaderItem
, SelectionCell
, ContentItem
, and CommandItem
objects.
The main two tasks of the DataCatalog
web control are: create the control hierarchy, and handle the child control events.
The CreateControlHierarchy
method handles the child controls creation. The HeaderItem
and CommandItem
are created at the beginning and at the end, respectively. For each data item in the data source, a ContentItem
object is created. A single SelectionCell
object is created.
protected virtual void CreateControlHierarchy(bool useDataSource)
{
...
foreach(object dataItem in data)
{
if (columnNames==null)
{
HeaderItem headerItem = new HeaderItem(columnNames, orderByColumnName);
if (useDataSource)
headerItem.DataBind();
this._dataCatalogTable.Rows.Add(headerItem);
}
ContentItem newItem = new ContentItem(columnNames, itemsCount,
this.DataFieldsFormat, this.ColumnsStyle);
if (useDataSource)
{
newItem.DataItem = dataItem;
newItem.DataBind();
}
this._dataCatalogTable.Rows.Add(newItem);
itemsCount++;
}
if (itemsCount>0)
{
outerRow.Cells.AddAt(0, new SelectionCell(itemsCount));
outerTable.Rows.Add(new CommandItem());
}
...
}
The DataCatalog
web control overrides the OnBubbleEvent
event to handle all the events of the child controls.
protected override bool OnBubbleEvent(object source, EventArgs e)
{
if (e is DataOperationCommandEventArgs)
{
DataOperationCommandEventArgs args = (DataOperationCommandEventArgs)e;
if (args.DataOperation==DataOperation.Delete)
{
DataKey dataKey = this.GetSeletedDataKey();
if (dataKey!=null)
{
this.DbDataExecute.SqlDeleteText = this.DeleteText;
if (this.DbDataExecute.ExecuteDelete(
this.GetDataKeyValues(dataKey), null)>0)
this.DataBind();
}
}
else if (args.DataOperation==DataOperation.Insert)
{
this.Context.Response.Redirect(
string.Format("{0}?Mode=Add",
this.InsertRedirectUrl), true);
}
else if (args.DataOperation==DataOperation.Update)
{
DataKey dataKey = this.GetSeletedDataKey();
if (dataKey!=null)
{
this.Context.Response.Redirect(
string.Format("{0}?Mode=Edit&{1}",
this.UpdateRedirectUrl,
this.BuildSelectDataItemUrlString(this.GetDataKeyValues(dataKey))),
true);
}
}
return true;
}
else if (e is OrderByCommandEventArgs)
{
OrderByCommandEventArgs args = (OrderByCommandEventArgs)e;
if (StringHelper.IsEmpty(this.OrderByColumnSelectText))
throw new Exception("Specify the OrderByColumnSelectText property value.");
this._orderByColumnName = args.ColumnName;
this._orderByEnabled = true;
this.DataBind();
this._orderByColumnName = string.Empty;
this._orderByEnabled = false;
return true;
}
else if (e is SelectItemEventArgs)
{
SelectItemEventArgs args = (SelectItemEventArgs)e;
string urlString = this.BuildSelectDataItemUrlString(
this.GetDataKeyValues(this.DataKeyManager.GetItemAt(args.Item.ItemIndex)));
if (StringHelper.IsEmpty(this.DetailsRedirectUrl))
throw new Exception("Specify the DetailsRedirectUrl property value.");
this.Context.Response.Redirect(
string.Format("{0}?Mode=ReadOnly&{1}",
this.DetailsRedirectUrl, urlString), true);
return true;
}
return false;
}
The following table has a list of the events handled by the DataCatalog
web control:
Event |
Description |
Delete |
The selected record is deleted. The DataKeyNames property is used to get the values that identify the record to delete. |
Insert |
Redirects the user to the web form used to insert data. |
Update |
Redirects the user to the web form used to update data. The DataKeyNames property is used to generate a query string used to identify the record to update. |
Order |
Orders the data by the selected data column. The OrderByColumnSelectText property is used to order the data. The [COLUMNNAME] tag is replaced with the name of the selected column. |
Select |
Redirects the user to the web form used to select data. The DataKeyNames property is used to generate a query string used to identify the selected record. |
InsertRedirectUrl, UpdateRedirectUrl, and DetailsRedirectUrl properties
We will use the BuilderEditor
web control to build the web forms used to insert, update, and display data. The BuilderEditor
web control generates the controls used to insert, update, and display data. You can download a free BuilderEditor developer version here.
To create the content of the web forms used to insert, update, and display data, we need to:
- Drag the
BuilderEditor
web control to the design surface.
- Then, right-click and select the Property Builder option from the context menu option.
- Right-click in the Available fields area, and then select the Fields editor option.
- Specify the data fields.
- Select the controls to be used to insert, update, and display data.
- Click OK to save changes.
- The input controls to insert, update, and display data are generated.
This article has covered the main features of the DataCatalog
web control. For full details, download the code. Download the BuilderEditor
and read the documentation for more details about how to use it.