Creating Custom Label Controls
 
Published: 29 Nov 2007
Abstract
This article looks at how to extend the label control to make a more complex label control that is reusable and more functional.
by Brian Mains
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 25018/ 41

Introduction

The label control is a simple control for rendering output or other HTML-based content. Overall, the label is somewhat limited in what it can do, as compared to the other .NET controls. For instance, a label can only render the text it has been given, and can show/hide that text. What about more complicated situations? This article will look at some possible additions to the control.

Data Bound List Issue

When used in a data binding situation, the label is often used to represent read-only data. When the data bound control is rendered in edit mode, a text box is used to edit the data. However, sometimes a list is used, which performs two bindings (depending on the situation). The first binding is the binding of all the possible values in the list. The second binding is which value was selected in the list. However, in view mode, this means some challenges; for instance, oftentimes the value stored in the database is an encoded value (like O for Open and C for close). This means that the value has to be converted, which may not be a challenge.

Let's use for example a United States state code field.  In the database, it stores PA for Pennsylvania, NY for New York, etc.  In edit mode, a drop down list is used, showing Pennsylvania and New York values spelled out; however, the underlying value is the encoded two-letter form.  In read-only mode, whenever the main data source is bound, it only knows about the two-letter form.

There are multiple solutions to this. The first is to translate the value. The GridView control has a RowDataBound method that can be used to tap into the rows/cells, and change the value stored in the cell (if that is the control that is being used). Another alternative is to include both the code and the name in the underlying data source. But with a little customization, another alternative is possible; that is what we will look at next.

ListLabel Control

The base ListControl class is the base class for controls like DropDownList, RadioButtonList, CheckBoxList, etc. This control has the ability to manually add items to the list, as well as supporting data binding the items into the collection.

The ListLabel control is a custom control that plugs into the existing framework for creating list controls; however, instead of rendering an interface that has to be manipulated, it simply renders the item that is stored in the collection marked as selected. Selection occurs in many ways in the ListControl base class, either through the SelectedIndex or SelectedValue properties. And because that is also handled for us, the following approach is very simple to use to render the content out to the screen.

Listing 1

protected override void Render(HtmlTextWriter writer)
{
  base.AddAttributesToRender(writer);
 
  if (!this.DesignMode)
  {
   //Get the selected item
    ListItem item = this.SelectedItem;
    //If the item exists, write out the text value
    if (item != null)
      writer.Write(item.Text);
    else
      writer.Write(this.EmptyDisplayText);
  }
 
  //Else in design mode, then render specific texts
  else
  {
    //If bound using a data source ID, write that it is bound
    if (this.DataSourceID != null)
      writer.Write("Databound");
    //Else write the ID
    else
      writer.Write("[" + this.ID + "]");
  }
}

The following code gets the selected item in the list. If no selection exists (SelectedIndex equals -1), the response of the EmptyDisplayText value is written, which is a string that simply takes a descriptive message to display. This method also takes care of handling design mode, by writing a Databound message when the databinding has been setup in the designer, or by simply writing the ID of the control otherwise.

This control is optimal to be used in view mode of a GridView, where edit mode will be using a DropDownList or RadioButtonList.

Listing 2

<asp:GridView ..>
  <Columns>
    <asp:TemplateField HeaderText="State">
       <ItemTemplate>
        <cc1:ListLabel id="lblState" runat="server" 
        DataSourceID="sdsStates" 
        SelectedValue='<%# Eval("StateCode") %>' />
       </ItemTemplate>
       <EditItemTemplate>
        <asp:DropDownList id="ddlState" runat="server"
        DataSourceID="sdsStates"
        SelectedValue='<%# Eval("StateCode") %>' />
      </EditItemTemplate>
   </asp:TemplateField>
  </Columns>
</asp:GridView>
Rendering Label Messages Issue

A label is often used as a warning of some sort. It often warns the user of some action; however, when the form is in view, edit, insert, or even audit mode, that message usually changes to be more appropriate. Oftentimes the code is not located in the same place, meaning that one has to dig through the code to figure out where the message is being rendered.

Optimally, the messages should be stored in a constant or in a resource file, but that does not always happen.  As an alternative, it is better to clean it up using one of those approaches, or the following control can be used to store the label's text in the ASPX content.

ListLabel Solution

Using the list label control and setting the SelectedValue or SelectedIndex, switches the appropriate message, making it easy to display the right message at the right time. One can set a message using the same construct as any list control:

Listing 3

ucListLabel.SelectedValue = "Intro";

The new message appears when the control is rendered.

The following is a complete code listing, most of which is shown above:

Listing 4

using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace Nucleo.Web.Controls
{
  public class ListLabel: ListControl
  {
    public string EmptyDisplayText
    {
      get
      {
        object o = ViewState["EmptyDisplayText"];
        return (o == null) ? "N/A" : (string)o;
      }
      set
      {
        ViewState["EmptyDisplayText"] = value;
      }
    }
 
    protected override void Render(HtmlTextWriter writer)
    {
      base.AddAttributesToRender(writer);
 
      if (!this.DesignMode)
      {
        //Get the selected item
        ListItem item = this.SelectedItem;
        //If the item exists, write out the text value
        if (item != null)
          writer.Write(item.Text);
        else
          writer.Write(this.EmptyDisplayText);
      }
 
      //Else in design mode, then render specific texts
      else
      {
        //If bound using a data source ID, write that it is bound
        if (this.DataSourceID != null)
          writer.Write("Databound");
        //Else write the ID
        else
          writer.Write("[" + this.ID + "]");
      }
    }
  }
}
Conclusion

You can see how a simple control adds a lot of functionality to an application, as well as adds to the ease of use.



User Comments

Title: fert   
Name: fo kos
Date: 2012-12-10 8:56:24 AM
Comment:
fo kos kos ley kos
Title: Nice Addition   
Name: Michael Davey
Date: 2007-11-29 8:46:40 AM
Comment:
Neat additions to the label control.. thanks!






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


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-16 8:24:41 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search