Selector Radio Button for GridView
A radio button to select a record in an ASP.NET GridView control.
Introduction
The ASP.NET GridView
control provides a way to present an HTML table of records from a database table. Data binding is supported to easily populate the GridView
. The BoundField
class provides the values of columns as text in the HTML table. There are also classes that provide for some of the common controls that you would want to use in the HTML table columns: check boxes, images, buttons, and links. In addition, the TemplateField
class is provided for completely customisable representations of data in a GridView
.
While the CheckBoxField
class that is provided can be used to select multiple records in a GridView
control, sometimes, there is a requirement to only allow a single record to be selected. In this case, a radio button makes more sense than a check box. However, there is no class in ASP.NET for putting a radio button in a column of a GridView
.
It is very straightforward to add a TemplateField
in the page designer to add a column of radio buttons to a GridView
. However, adding such a radio button in code dynamically, at runtime, is not as straightforward. This requires creating a new class that inherits from TemplateField
and a new class that implements the ITemplate
interface in order to provide the customized rendering of the radio buttons.
The SelectorRadioButtonField
class presented in this article is a customised TemplateField
that can be used to include a radio button column in a GridView
. The radio buttons are rendered as standard HTML <input>
fields of type "radio
". The "value
" attribute of each radio button is used to indicate the primary key value of the selected record.
The SelectorRadioButtonField
includes the following features:
- Allows for data binding of the "
value
" attribute of the radio button to the primary key column of the database table. - Allows for data binding of other attributes of the radio button.
- Allow for client-side enabling and disabling of action buttons based on the record that is currently selected. This can use attributes of the radio button that have been bound to other columns.
Using the code
Download the demo project. This is a web application project that demonstrates the SelectorRadioButtonField
being used on a GridView
control. The web application consists of a single web page (Default.aspx) with a GridView
that displays the records in the Orders table from the Northwind database. The data is stored in an XML file that is part of the project, so you don't need to have a SQL Server database with the Northwind database in order to run the demo project.
Use the demo project code to help follow the information provided on how to use the code.
There are four main steps required to incorporate the SelectorRadioButtonField
in your project and use it in a GridView
control:
- Add the SelectorRadioButtonField.cs code file
- Add the SelectorRadioButton.js code file
- Add code to the code-behind class of a page or control containing a
GridView
- Add JavaScript code to a page or control containing a
GridView
Each of these steps is explained further below. The first two steps only need to be done once in your project. The third and fourth steps need to be done for each GridView
control in which you use the SelectorRadioButtonField
.
Following the explanation of the steps to incorporate the SelectorRadioButtonField
in your project and use it in a GridView
control, there is an explanation of the code.
Add the SelectorRadioButtonField.cs code file
In an appropriate folder in your project, add the SelectorRadioButtonField.cs code file from the demo project. This code file contains the SelectorRadioButtonField
class. The SelectorRadioButtonField
class contains two private classes that are used internally to the SelectorRadioButtonField
class, and two public collection classes used to support two of the properties of the SelectorRadioButtonField
class. Each of these classes is described later.
You may want to change the namespace for the SelectorRadioButtonField
to something that is compatible with your own project.
Add the SelectorRadioButton.js code file
In an appropriate folder in your project, add the SelectorRadioButton.js code file from the demo project. This code file contains the SelectRadioButton
JavaScript function. This function is used to select the instance of a radio button on a page with a specific name and value.
Alternatively, instead of creating a separate file for the SelectRadioButton
JavaScript function, you can add this function to another JavaScript code file that is part of your project. The only requirement is that the SelectRadioButton
JavaScript function is loaded for each page with a GridView
that uses the SelectorRadioButtonField
.
Add code to the code-behind class
The SelectorRadioButtonField
is added to a GridView
control in code, rather than in the page designer. The code to add the SelectorRadioButtonField
needs to be added at a suitable place in the code-behind class for the page or user control containing the GridView
.
Code also needs to be added to support pre-selecting a record when the page containing the GridView
is displayed, and to determine the selected record when the page is posted back.
Add a public constant for the value of the Name property of the SelectorRadioButtonField
public const string SelectedOrderIDField = "SelectedOrderID";
It is recommended that you use a public
class constant for the value of the Name
property as it will be used in three places in your project.
In the demo project, SelectedOrderIDField
is a public
constant that has been defined in the code for the Default.aspx page.
Add a property for the Primary Key of the pre-selected record
private int? _preSelectedOrderID = null;
public int? PreSelectedOrderID
{
get { return _preSelectedOrderID; }
}
By default, when a page containing a GridView
control is displayed, none of the radio buttons will be selected. The SelectRadioButton
JavaScript function that has been added to your project can be used to pre-select one of the radio buttons. To provide access to the Primary Key value of the record to be pre-selected, we will add a public read-only property (and private backing variable). We will see how this is used with the SelectRadioButton
JavaScript function later.
In the demo project, PreSelectedOrderID
is a public property that has been defined in the code for the Default.aspx page. _preSelectedOrderID
is the private backing variable for this property.
Add SelectorRadioButtonField to the GridView
At a suitable place in the code-behind class for the page or user control containing the GridView
, add code to include a SelectorRadioButtonField
.
The SelectorRadioButtonField
needs to be added to a GridView
control before the data binding is invoked (i.e., before the DataBind
method of the GridView
is called).
In the demo project, SelectorRadioButtonField
is added to the GridView
control in the Page_PreRender
method for the Default.aspx page.
Create a new instance of the SelectorRadioButtonField
SelectorRadioButtonField selectorRadioButtonField = new SelectorRadioButtonField();
or
SelectorRadioButtonField selectorRadioButtonField =
new SelectorRadioButtonField(SelectedOrderIDField,
ordersDataTable.OrderIDColumn.ColumnName);
Declare a new local variable of type SelectorRadioButtonField
and set it to a new SelectorRadioButtonField
instance.
Note: You may need to add a new using
statement to your code file if SelectorRadioButtonField
is in a namespace that is not already referenced.
There are two constructors provided for SelectorRadioButtonField
. If you use the default constructor (no parameters), you must set the Name
and ValueDataField
properties. A second constructor takes values for each of these properties so they do not need to be set explicitly.
Set the Name property of the SelectorRadioButtonField
selectorRadioButtonField.Name = SelectedOrderIDField;
The Name
property must be set. This will be used as the value of the "name
" attribute of the <input>
element for the radio button that is rendered for each row in the GridView
.
If you have provided the value for the Name
property in the SelectorRadioButtonField
constructor, you do not need to set the property explicitly.
Note: It is recommended that you use a public class constant for the value of the Name
property as it will be used in three places in your project. In the demo project, the SelectedOrderIDField
constant is used.
Set the ValueDataField property of the SelectorRadioButtonField
selectorRadioButtonField.ValueDataField = ordersDataTable.OrderIDColumn.ColumnName;
The ValueDataField
property must be set. This needs to be the column name of the Primary Key column of the DataTable
that will be bound to the GridView
control. This will be used as the value of the "value
" attribute of the <input>
element for the radio button that is rendered for each row in the GridView
. When the page is posted back, the Form variables of the request will include a variable with the name of the "name
" attribute and the value of the "value
" attribute of the radio button that has been selected.
If you have provided the value for the ValueDataField
property in the SelectorRadioButtonField
constructor, you do not need to set the property explicitly.
Note: It is recommended that you use a constant for the value of the ValueDataField
property. Alternatively, if your application uses Typed DataSets, you can use the property for the Primary Key column that is generated by the DataSet Designer. In the demo project, OrderIDColumn.ColumnName
is the value generated for OrdersDataSet.OrdersDataTable
.
Add the SelectorRadioButtonField to the Columns collection of the GridView
OrdersGridView.Columns.Add(selectorRadioButtonField);
The new instance of the SelectorRadioButtonField
needs to be added to the Columns
collection of the GridView
. If all the columns in the GridView
are added in code, you can simply use the Add
method of the Columns
property of the GridView
. If other columns have been added to the GridView
in the Page Designer, then you can use the Insert
method of the Columns
property of the GridView
to control where in the column order the SelectorRadioButtonField
is included.
Set the OnClick property of the SelectorRadioButtonField (Optional)
If you want to execute a client script each time the user clicks one of the radio buttons, then add the required script to the OnClick
property of the SelectorRadioButtonField
. This will be used as the value of the "onclick
" attribute of the <input>
element for the radio button that is rendered for each row in the GridView
.
For example, one of the main uses of the SelectorRadioButtonField
is to allow the user to select a record on which to perform some further action (e.g., edit the record, delete the record). Buttons are usually provided on the page to invoke each of the possible actions for the currently selected record. If you want to enable and disable some action buttons depending on the record that is currently selected, then include client script to enable and disable buttons in the OnClick
property.
In the demo project, the "View Ship Region" button (cmdViewShipRegion
) is only enabled if the currently selected Order has a value in the ShipRegion column. A JavaScript function called enableDisableButtons
has been included on the Default.aspx page to manage this. For the SelectorRadioButtonField
, the OnClick
property has been set to the JavaScript required to call the enableDisableButtons
function, passing the current instance of the radio button as a parameter.
selectorRadioButtonField.OnClick = "enableDisableButtons(this)";
Add to the AttributeBindings property of the SelectorRadioButtonField (Optional)
If you want to include additional attributes in the <input>
element for the radio button that is rendered for each row in the GridView
, and the value of the attribute should be dependant on the current row in the GridView
(i.e., is bound to a column in the bound DataTable
), then add an item to the AttributeBindings
property of the SelectorRadioButtonField
.
Adding attributes in this way can be used to set any attribute, either standard attributes for an <input>
element (such as "title
"), or custom attributes that can be used by the client script.
For example, in conjunction with the client script to enable/disable action buttons, custom attributes can be used to provide values used to determine whether to enable or disable buttons.
In the demo project, the "View Ship Region" button (cmdViewShipRegion
) is only enabled if the currently selected Order has a value in the ShipRegion column. A JavaScript function called enableDisableButtons
has been included on the Default.aspx page to manage this. For the SelectorRadioButtonField
, an item has been added to the AttributeBindings
property to include an attribute called "shipRegion
" that is bound to the value of the "ShipRegion" column. The "shipRegion
" attribute is used by the called enableDisableButtons
function.
selectorRadioButtonField.AttributeBindings.Add("shipRegion",
ordersDataTable.ShipRegionColumn.ColumnName);
Add to the UnBoundAttributes property of the SelectorRadioButtonField (Optional)
If you want to include additional attributes in the <input>
element for the radio button that is rendered for each row in the GridView
, and the value of the attribute will be the same for each row in the GridView
, then add an item to the UnBoundAttributes
property of the SelectorRadioButtonField
.
Adding attributes in this way can be used to set any attribute, either standard attributes for an <input>
element (such as "title
"), or custom attributes that can be used by the client script.
In the demo project, an item has been added to the UnBoundAttributes
property to include an attribute called "title
" with a value of "Click to select". "title
" is a standard HTML attribute that is used by browsers such as Internet Explorer to provide a tooltip.
selectorRadioButtonField.UnBoundAttributes.Add(HtmlTextWriterAttribute.Title.ToString(),
"Click to select");
Set other TemplateField properties (Optional)
You can set other properties that are inherited from the base TemplateField
class.
For example, you may want to provide a value for the HeaderText
property. The following code will include the word "Select" as the header for the radio button column:
selectorRadioButtonField.HeaderText = "Select";
You may want to customise the ItemStyle
property. By default, the ItemStyle
property for SelectorRadioButtonField
has centered horizontal alignment and is 40 pixels wide. The following code will change the width to 50 pixels:
selectorRadioButtonField.ItemStyle.Width = new Unit(50, UnitType.Pixel);
Add code to determine the selected record
When the page containing the GridView
is posted back, it may be necessary to determine the record in the GridView
that is currently selected. For example, if the user has clicked a button to perform some action for the currently selected record, the selected record can be determined based on the particular radio button that was selected by the user.
Note: the radio buttons that are rendered are not ASP server controls, so cannot be accessed in code directly.
When the page is posted back, the Form variables of the request will include a variable with the name of the Name
property of the SelectorRadioButton
and the value of the Primary Key for the currently selected record.
It is likely that you will need to determine the selected record for more than one action. Therefore, you should create a private method that determines the Primary Key of the selected record and returns it as the appropriate data type. This method can then be called from the Click
event handler methods for the action buttons.
Add a private method to get the Primary Key of the selected record
In the demo project, the Default.aspx page includes a private method called GetSelectedOrderID
.
private int GetSelectedOrderID()
{
// Find the selected Order ID in the form variables, ensure it is
// supplied and is an integer, return it as an integer.
string selectedOrderID = Request.Form[SelectedOrderIDField];
int orderId;
if (selectedOrderID == null)
{
// This should not happen.
throw new ApplicationException(string.Format(
"'{0}' was missing from Form fields.",
SelectedOrderIDField));
}
if (int.TryParse(selectedOrderID, out orderId))
{
return orderId;
}
else
{
throw new ApplicationException(string.Format(
"The value of the '{0}' Form field must be an integer."
+ " The value '{1}' is invalid.",
SelectedOrderIDField, selectedOrderID));
}
}
The value of the Primary Key of the selected record (the selected Order ID) is retrieved from the collection of Form variables (Request.Form
). The same constant that was used to set the Name
property of the SelectorRadioButtonField
is used as the index into the collection.
A check is made to ensure that the required Form variable was present in the request.
In the demo project, the OrderID column is an integer. The values in the collection of Form variables are provided as strings. The string value of the selected Order ID is converted to an integer. A check is made to ensure that the value of the selected Order ID is an integer.
The selected Order ID is returned as an integer.
Add calls to the private method to get the Primary Key of the selected record
In the demo project, the Default.aspx page includes an event handler method for the "View Ship Region" button (cmdViewShipRegion_Click
). The code in this method calls the GetSelectedOrderID
method to get the Primary Key of the selected record. The selected Order ID is then used to perform the requested action for the selected record.
protected void cmdViewShipRegion_Click(object sender, EventArgs e)
{
// Get the Order ID of the selected Order, find the Order in the
// Orders that are saved in Session, set the message label to a
// message that includes the Ship Region of the Order.
_preSelectedOrderID = GetSelectedOrderID();
OrdersDataSet.OrdersDataTable ordersDataTable =
(OrdersDataSet.OrdersDataTable)Session[SessionOrders];
OrdersDataSet.OrdersRow ordersRow =
ordersDataTable.FindByOrderID(_preSelectedOrderID.Value);
lblMessage.Text = "You clicked View Ship Region for region " +
ordersRow.ShipRegion;
}
Add JavaScript code to the page or the control
There is JavaScript code that must be included on the page or the user control that will contain a GridView
control that uses the SelectorRadioButtonField
. This must be added within <script>
elements on the page or user control.
Add script to include the SelectRadioButton JavaScript function
The "SelectorRadioButton.js" file was added to your project. This file contains the SelectRadioButton
JavaScript function.
This file needs to be referenced in the page or control containing the GridView
control. This should be done using a <script>
element.
For example:
<script
type="text/javascript"
language="JavaScript"
src="/Scripts/SelectorRadioButton.js">
</script>
Add script to execute when a radio button is selected (Optional)
If you want to execute a client script each time the user clicks on one of the radio buttons, then add the required script to the OnClick
property of the SelectorRadioButtonField
. This will be used as the value of the "onclick
" attribute of the <input>
element for the radio button that is rendered for each row in the GridView
. See above for information on adding script to the "onclick
" attribute.
Unless the script to be included in the "onclick
" attribute is trivial, it is best to add the required script to a JavaScript function on the page or user control containing the GridView
, and just add a call to this function in the "onclick
" attribute.
For example, in the demo project, the "View Ship Region" button (cmdViewShipRegion
) is only enabled if the currently selected Order has a value in the ShipRegion column. A JavaScript function called enableDisableButtons
has been included on the Default.aspx page to manage this. For the SelectorRadioButtonField
, the OnClick
property has been set to the JavaScript required to call the enableDisableButtons
function, passing the current instance of the radio button as a parameter. The enableDisableButtons
JavaScript function is included in a <script>
element:
<script
type="text/javascript"
language="JavaScript">
function enableDisableButtons(radioButtonForSelectedOrder)
{
// get the View Ship Region button element
var cmdViewShipRegion =
document.getElementById('cmdViewShipRegion');
if (cmdViewShipRegion == null)
{
alert('Unable to locate View Ship Region button');
}
else
{
// enable or disable the View Ship Region button
cmdViewShipRegion.disabled =
(radioButtonForSelectedOrder.shipRegion == '');
}
}
</script>
Note: The custom "shipRegion
" attribute of the currently selected radio button is used to determine whether or not to enable the "View Ship Region" button.
Add script to call the SelectRadioButton JavaScript function
When the page containing the GridView
control is displayed, the SelectRadioButton
JavaScript function needs to be called to cause a radio button to be selected (either the radio button for a pre-selected record, or the first record if there is no pre-selected record or the pre-selected record is not on the page).
The simplest way of achieving this is to include a <script>
element after the <asp:GridView>
element on the page or user control. The JavaScript provided should call the SelectRadioButton
function, passing as parameters the name of the radio button to select and the value of the radio button to be selected. The value of the constant used to set the Name
property of the SelectorRadioButtonField
should be used for the radio button name parameter. The value of the property used for the pre-selected record should be used as the value parameter.
For example:
<asp:GridView
ID="OrdersGridView"
runat="server"
AutoGenerateColumns="False"
PageSize="8"
OnPageIndexChanging="OrdersGridView_PageIndexChanging"
EnableViewState="False">
<HeaderStyle CssClass="gridViewHeader" />
<RowStyle CssClass="gridViewRow" />
<PagerStyle CssClass="gridViewPager" />
</asp:GridView>
<script
type="text/javascript"
language="JavaScript">
SelectRadioButton('<%= SelectedOrderIDField%>',
'<%= this.PreSelectedOrderID%>');
</script>
If you have included a value for the optional OnClick
property of the SelectorRadioButtonField
, then you need to ensure you include a call to the same JavaScript after calling the SelectRadioButton
JavaScript function. The SelectRadioButton
JavaScript function returns a reference to the radio button that was selected by the function (null
if no button was selected). This reference can be used in the JavaScript that is executed when a radio button is selected.
For example, in the demo project, the enableDisableButtons
JavaScript function is called when a radio button is selected. The <script>
element that is included on the Default.aspx page is:
<script
type="text/javascript"
language="JavaScript">
var selectedRadioButton = SelectRadioButton(
'<%= SelectedOrderIDField%>', '<%= this.PreSelectedOrderID%>');
if (selectedRadioButton != null)
{
enableDisableButtons(selectedRadioButton);
}
</script>
In this case, the <script>
element must be placed after any other element on the page that will be referenced by the JavaScript that is called. For the demo project, the <script>
element must be placed after the "View Ship Region" button (cmdViewShipRegion
).
Explanation of the code
The SelectorRadioButtonField class
public class SelectorRadioButtonField : TemplateField
{
...
}
SelectorRadioButtonField
(in the SelectorRadioButtonField.cs code file) inherits from the TemplateField
class. The TemplateField
class uses the object assigned to its ItemTemplate
property to render the appropriate content for each row in the GridView
. The ItemTemplate
property must be assigned an instance of a class that implements the ITemplate
interface.
SelectorRadioButtonField
has a private field (_selectorRadioButtonItem
) whose type is a private class: SelectorRadioButtonItem
(see below).
private SelectorRadioButtonItem _selectorRadioButtonItem;
SelectorRadioButtonItem
implements the ITemplate
interface. In the SelectorRadioButtonField
constructor, _selectorRadioButtonItem
is set as the ItemTemplate
property for the base TemplateField
class.
SelectorRadioButtonField
has a number of public properties that wrap the same properties of the SelectorRadioButtonItem
instance.
public string Name
{
get { return _selectorRadioButtonItem.Name; }
set { _selectorRadioButtonItem.Name = value; }
}
public string ValueDataField
{
get { return _selectorRadioButtonItem.ValueDataField; }
set { _selectorRadioButtonItem.ValueDataField = value; }
}
public string OnClick
{
get { return _selectorRadioButtonItem.OnClick; }
set { _selectorRadioButtonItem.OnClick = value; }
}
public AttributeBindingsCollection AttributeBindings
{
get { return _selectorRadioButtonItem.AttributeBindings; }
}
public UnBoundAttributesCollection UnBoundAttributes
{
get { return _selectorRadioButtonItem.UnBoundAttributes; }
}
The purpose of the properties is described in the section below for SelectorRadioButtonItem
.
SelectorRadioButtonField
overrides the ItemTemplate
property of the base TemplateField
class. This helps prevent the ItemTemplate
property being accessed, as the ItemTemplate
for the SelectorRadioButtonField
class is going to be managed internally (note that the ItemTemplate
property is not virtual
, so can still be accessed via the base TemplateField
interface).
Two constructors are provided:
public SelectorRadioButtonField()
{
_selectorRadioButtonItem = new SelectorRadioButtonItem();
base.ItemTemplate = _selectorRadioButtonItem;
ItemStyle.HorizontalAlign = HorizontalAlign.Center;
ItemStyle.Width = new Unit(40, UnitType.Pixel);
}
public SelectorRadioButtonField(string name, string valueDataField)
: this()
{
Name = name;
ValueDataField = valueDataField;
}
The first constructor creates a new instance of the SelectorRadioButtonItem
class and assigns it to the _selectorRadioButtonItem
instance variable and to the ItemTemplate
property of the base TemplateField
class. The ItemStyle
of the TemplateField
is set to be center aligned horizontally, and set to a width of 40 pixels.
The second constructor extends the first constructor, and allows the values of the Name
and ValueDataField
properties to be set.
SelectorRadioButtonField
includes two private classes that are used internally: SelectorRadioButtonItem
and SelectorRadioButton
. These are described below.
SelectorRadioButtonField
also includes two public collection classes that are used to support two properties of the SelectorRadioButtonField
class: AttributeBindings
and UnBoundAttributes
. These are described below.
The SelectorRadioButtonItem class
private class SelectorRadioButtonItem : ITemplate
{
...
}
SelectorRadioButtonItem
implements the ITemplate
interface. SelectorRadioButtonItem
is used to control the rendering of the appropriate content for each row in the GridView
.
Properties
To support rendering of the appropriate content for the SelectorRadioButtonField
, the class has five properties, with associated private fields. These are:
Name
. This is used as the "name
" attribute of the HTML<input>
field that is rendered for the radio button.ValueDataField
. This is the name of a column in the data source that will be bound to theGridView
control. The value should be the name of the Primary Key column. This will be used as the value of the "value
" attribute of the HTML<input>
field that is rendered for the radio button.OnClick
. This is used as the value of the "onclick
" attribute of the HTML<input>
field that is rendered for the radio button. This allows a JavaScript function to be called when the user selects one of the radio buttons.AttributeBindings
. This is aDictionary
with string keys and string values. This can be used to add other data bound attributes to the HTML<input>
field that is rendered for the radio button. The key of anAtrributeBindings
item will be the name of the attribute that is rendered. This can be either a known attribute for an HTML<input>
field, or it can be a custom attribute. The value of anAtrributeBindings
item will be the name of a column in the data source that will be bound to theGridView
control. The value of this column will be the value of the attribute that is rendered.UnBoundAttributes
. This is aDictionary
with string keys and string values. This can be used to add other attributes to the HTML<input>
field that is rendered for the radio button. The key of anUnBoundAttributes
item will be the name of the attribute that is rendered. This can be either a known attribute for an HTML<input>
field, or it can be a custom attribute. The value of anUnBoundAttributes
item will be the string value of the attribute that is rendered (i.e., it will be the same for each radio button that is rendered in the column of theGridView
).
The ITemplate Interface
SelectorRadioButtonItem
implements the ITemplate
interface. The only member of the ITemplate
interface is the InstantiateIn
method. You do not need to call this method. The InstantiateIn
method is invoked by ASP.NET when an instance of the template needs to be created inside its parent (container) control.
public void InstantiateIn(Control container)
{
SelectorRadioButton radioButton = new SelectorRadioButton();
radioButton.DataBinding += new EventHandler(radioButton_DataBinding);
if (string.IsNullOrEmpty(_name))
{
throw new InvalidOperationException("The Name property " +
"for SelectorRadioButtonField has not been set.");
}
else
{
radioButton.Name = _name;
}
if (!string.IsNullOrEmpty(_onClick))
{
radioButton.Attributes.Add(HtmlTextWriterAttribute.Onclick.ToString(),
_onClick);
}
foreach (string key in _unBoundAttributes.Keys)
{
radioButton.Attributes.Add(key, _unBoundAttributes[key]);
}
container.Controls.Add(radioButton);
}
In the InstantiateIn
method, we create a SelectorRadioButton
control (see below) to be rendered as the content of the GridView
column. This will be added to the child controls of the container control in which we are being rendered.
For the content of the column, we need to use a control that supports data binding. Our SelectorRadioButton
control inherits from the HtmlInputRadioButton
, which supports data binding. We add an event handler for the DataBinding
event of the SelectorRadioButton
control.
Using the values that have been set for the Name
, OnClick
, and UnBoundAttributes
properties, we add attributes to the SelectorRadioButton
control.
Data-binding
In the DataBinding
event of the SelectorRadioButton
control, we will add attributes to the SelectorRadioButton
control for each of the bound fields.
private void radioButton_DataBinding(object sender, EventArgs e)
{
SelectorRadioButton radioButton = (SelectorRadioButton)sender;
GridViewRow container = (GridViewRow)radioButton.NamingContainer;
DataRowView row = (DataRowView)container.DataItem;
if (string.IsNullOrEmpty(_valueDataField))
{
throw new InvalidOperationException("The ValueDataField property" +
" for SelectorRadioButtonField has not been set.");
}
else
{
radioButton.Value = row[_valueDataField].ToString();
}
foreach (string key in _attributeBindings.Keys)
{
radioButton.Attributes.Add(key, row[_attributeBindings[key]].ToString());
}
}
First, we get the sender
object of the event as a SelectorRadioButton
. This allows us to access the properties of the SelectorRadioButton
. We get the value of the NamingContainer
property. As the SelectorRadioButton
is being rendered in a GridView
, the NamingContainer
will be a GridViewRow
. This allows us to access the DataItem
property, which will be a DataRowView
object for the bound DataTable
.
We set the Value
property of the SelectorRadioButton
to the value of the column that is set as the ValueDataField
.
We add attributes to the SelectorRadioButton
control that has been added to AttributeBindings
, with values from the bound fields.
The SelectorRadioButton class
private class SelectorRadioButton : HtmlInputRadioButton
{
...
}
SelectorRadioButton
is used to render the content for each row in the GridView
.
SelectorRadioButton
inherits from the HtmlInputRadioButton
class. SelectorRadioButton
needs to be inherited at least from Control
in order to support data-binding. Inheriting from HtmlControl
adds support for the Attributes
property. HtmlInputRadioButton
is used as the base class as it already supports the Name
and Value
properties that we want to use.
We override the protected
Render
method to control the precise rendering of the content.
protected override void Render(HtmlTextWriter output)
{
foreach (string key in Attributes.Keys)
{
output.AddAttribute(key, Attributes[key]);
}
output.RenderBeginTag(HtmlTextWriterTag.Input);
output.RenderEndTag();
}
All of the attributes that have been defined for the SelectorRadioButton
are included in the <input>
element that is rendered. This will include the "name
" and "value
" attributes that have been defined using the Name
and Value
properties of the HtmlInputRadioButton
class.
Note: We cannot use HtmlInputRadioButton
directly as ASP.NET will render each radio button with a unique name (fully qualified with all the container names), which does not allow us to determine the selected value associated with the radio button when the page is posted back.
The AttributeBindingsCollection and UnBoundAttributesCollection classes
public class AttributeBindingsCollection : Dictionary<string, string>
{
...
}
public class UnBoundAttributesCollection : Dictionary<string, string>
{
...
}
AttributeBindingsCollection
and UnBoundAttributesCollection
are used to provide customised Dictionary
classes for the AttributeBindings
and UnBoundAttributes
properties of the SelectorRadioButtonField
class.
AttributeBindingsCollection
and UnBoundAttributesCollection
both inherit from Dictionary<string, string>
. The only method added to these classes is a new Add
method that hides the Add
method of the Dictionary
. This serves two purposes:
- The names of the
key
andvalue
parameters have customised names (attribute
anddataField
forAttributeBindingsCollection
, andattribute
andvalue
forUnBoundAttributesCollection
) and are documented with comments that appear in Intellisense. This improves developer understanding of how to use theAttributeBindings
andUnBoundAttributes
properties of theSelectorRadioButtonField
class. - The
attribute
name that is used as the Dictionarykey
is validated to ensure it is not one of the attributes for which a specific property is provided (name
,value
, andonclick
).
The SelectRadioButton JavaScript function
The SelectRadioButton
JavaScript function (in the SelectorRadioButton.js code file) is used to select the instance of a radio button on a page with a specific name and value.
When the SelectorRadioButtonField
is used in a GridView
, each row in the HTML table that is rendered will have a radio button with the same value for the "name
" attribute, and a "value
" attribute with a value of the Primary Key of the record displayed in the table row. By default, when the containing page is displayed, none of the radio buttons will be selected. The SelectRadioButton
function allows one of the radio buttons to be selected by default.
SelectorRadioButton.js is a reusable JavaScript file. It needs to be included on any page in your project that uses a GridView
control with a SelectorRadioButtonField
. You only need to add this code file once to your project.
Instead of creating a separate file for the SelectRadioButton
JavaScript function, you can add this function to another JavaScript code file that is part of your project. The only requirement is that the SelectRadioButton
JavaScript function is loaded for each page with a GridView
that uses the SelectorRadioButtonField
.
function SelectRadioButton(radioButtonName, value)
{
// If a radio button with the given name and value exists,
// then make it selected. Otherwise, make the first radio
// button with the given name selected.
var selectedRadioButton = null;
var radioButtons = document.getElementsByName(radioButtonName);
if (radioButtons.length > 0)
{
selectedRadioButton = radioButtons[0];
if (value != null && value != '')
{
for (i = 0; i < radioButtons.length; i++)
{
if (radioButtons[i].value == value)
{
selectedRadioButton = radioButtons[i];
break;
}
}
}
}
if (selectedRadioButton != null)
{
selectedRadioButton.checked = true;
}
return selectedRadioButton;
}
SelectRadioButton
receives two parameters:
radioButtonName
– the string name of the radio button to be selected.value
– the value of the radio button to be selected.
We use the getElementsByName
method of the current document
object, to get an array of all the radio buttons with the given radioButtonName
.
Provided there is at least one radio button with this name, we iterate through the array of radio buttons and examine the value
attribute of each. If the value
attribute matches the given value
parameter, then that radio button will be selected (checked
attribute set to true
).
If there is at least one radio button with the given name, but no radio buttons with the given value, then the first radio button with the given name will be selected.
If a radio button has been selected, the selected radio button is returned by the function.
History
- March 3, 2008 - Original article.