Creating Custom Data Field Controls - Part 1
page 4 of 5
by Brian Mains
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 29798/ 146

A Custom Base Class

I am going to move onto a base class I created to help with some of the basic interactions in creating custom data control fields.

The first method overrides ExtractValuesFromCell, which does not have a lot of use in a base class. This is because the real meaning of this method is to extract the underlying values of the editing control and provide them to the data source, which none of this is known yet (exposed by the consumer). The following implementation simply determines if the rendering is in insert mode.

Listing 8

public override void ExtractValuesFromCell(IOrderedDictionary dictionary, 
  DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
      //base.ExtractValuesFromCell(dictionary, cell, rowState, includeReadOnly);
      _insertMode = (rowState == DataControlRowState.Insert);
}

The next method that is helpful extracts an instance of a control from within the cell, making it easier to get a strongly-typed reference. It performs checking to make sure that the control really does exist at the specified cell index.

Listing 9

protected T ExtractControl<T>(TableCell cell, int controlIndex) where T : Control
{
      if (cell == null)
            throw new ArgumentNullException("cell");
      if (controlIndex < 0 || controlIndex >= cell.Controls.Count)
            throw new ArgumentOutOfRangeException("index", Errors.OUT_OF_RANGE);
 
      Control control = cell.Controls[controlIndex];
      if (control == null)
            throw new InvalidOperationException(Errors.CANT_EXTRACT_CONTROL);
 
      return (T)control;
}

The next method is very helpful in reflecting against the underlying data type, and pulling out the real value. Note that the DataBinder method is used, so the method does not use a new approach to extracting the values, but compacts the approach to retrieve the underlying value.

Listing 10

protected object GetDataItemValue(object container, string propertyName)
{
      if (container == null || this.DesignMode)
            return null;
 
      //Get the data item from the container
      object dataItem = DataBinder.GetDataItem(container);
      if (dataItem == nullreturn null;
      object value = null;
 
      if (!propertyName.Contains("."))
            //Get the value from the data item
            value = DataBinder.GetPropertyValue(dataItem, propertyName);
      else
      {
            value = dataItem;
            string[] propertyList = propertyName.Split('.');
 
            foreach (string propertyItem in propertyList)
            {
                  value = DataBinder.GetPropertyValue(value, propertyItem);
                  if (value == nullreturn null;
            }
      }
 
      return value;
}

The next method performs read-only formatting, making it easier to alter the read-only value that is rendered in the cell. Though in the base class there is not any meaning to this yet, it comes in handy later. For instance, for a numeric field I provided two properties called Prefix and Suffix, which append that text to the value itself. So, I could append a "$" and a ".00" to make a field look like a whole number monetary amount.

Listing 11

protected virtual string GetReadOnlyValue(object initialValue)
{
      if (initialValue != null)
            return initialValue.ToString();
      else
            return null;
}

For some reason, the data control field base class requires that the field be created through the CreateField method. Why not use reflection and handle this automatically? The following method does just that.

Listing 12

protected override DataControlField CreateField()
{
      return (DataControlField)Activator.CreateInstance(this.GetType());
}

In addition, the code that adds a data item to the underlying dictionary (which stores all the values that will be passed to the underlying data source) is simple code, but it helps not to have to repeat it over and over. Below is the code to check the dictionary for the existence of a dictionary entry by the name, and the appropriate method call to update it.

Listing 13

protected virtual void AddDictionaryEntry(IOrderedDictionary dictionary,
  string dataField, object value)
{
      if (dictionary == null)
            throw new ArgumentNullException("dictionary");
      if (string.IsNullOrEmpty(dataField))
            throw new ArgumentNullException("dataField");
 
      if (dictionary.Contains(dataField))
            dictionary[dataField] = value;
      else
            dictionary.Add(dataField, value);
}

View Entire Article

User Comments

Title: A test title   
Name: Hassan
Date: 2008-06-30 10:37:25 AM
Comment:
very good article.
Title: Awesome!   
Name: AzamSharp
Date: 2008-06-26 12:17:36 AM
Comment:
Hi,

Very nice article! I think I am going to look into creating some custom data field controls myself.
Title: Nice article   
Name: Joydip Kanjilal
Date: 2008-01-04 12:16:56 PM
Comment:
Nice article Brian.

Thanks,

Joydip

Author: ASP.NET Data Presentation Controls Essentials (Packt Publishing)

http://www.packtpub.com/asp-net-data-presentation-controls/book






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2019 ASPAlliance.com  |  Page Processed at 2019-05-25 3:15:43 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search