|
Creating Custom Label Controls
|
by Brian Mains
Feedback
|
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days):
25018/
52
|
|
|
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.
|
|
|
|
|
|