扩展GridView之添加单选列
背景:实现GridView的单选列,传统的做法应该是新增模板列,然后添加RadioButton,客户端实现单选,后台遍历读取选中行数据。
第一:添加模板列,加入RadioButton。为了取值方便,我把记录的主键放在HiddenField中保存。
<ItemTemplate>
<asp:RadioButton ID="rbChecked" runat="server" onclick="rbCheck(this.id)" />
<asp:HiddenField ID="hidID" Value ='<%# Eval("ID") %>' runat="server" />
</ItemTemplate>
</asp:TemplateField>
发现问题:生成的选择列并没有单选功能,解决过程:
1:设置RadionButton的GroupName,结果证明是不可行的。
2:RadionButton生成的html为input,可不可以设置name属性呢,结果也是不可行,因为GridView生成数据行的时候,会修改这个name值,使得最终的name值各不相同。
解决方案:在RadioButton发生客户端点击事件时,动态设置其它选择按钮的选中状态。例如上文中的onclick="rbCheck(this.id)"。这样可以实现单选的效果。
{
var gv = $("<%=this .GridView1 .ClientID %>");
//被选择的个数
var num=0;
for(i = 1;i < gv.rows.length; i++)
{
var inputArray = gv.rows[i].getElementsByTagName("input");
for(var j=0;j<inputArray.length;j++)
{
if(inputArray[j].type=='radio')
{
if(inputArray[j].id==obj)
{
inputArray[j].checked=true;
}
else
{
inputArray[j].checked=false;
}
}
}
}
}
后台的取值需要遍历GridView所有数据行,然后根据HiddenField和RadioButton的选中情况来取最后的记录的主键值。
/// 取选中行的ID
/// </summary>
/// <returns></returns>
private string getID()
{
string id="";
foreach (GridViewRow row in this.GridView1.Rows)
{
CheckBox cb = (CheckBox)row.FindControl("rbChecked");
if (cb != null && cb.Checked)
{
HiddenField hidID = (HiddenField)row.FindControl("hidID");
id = hidID.Value.ToString();
}
}
return id;
}
小结:上面的方案在功能上已经实现了单选列的效果,但如果这样的页面多几个的话,就需要考虑封装下,这里jillzhang以前扩展过GridView,他的文章的中实现了单选列功能。我在这里在单拿这一方面的功能总结一下如果扩展GridView实现新增模板列。GridView本身提供了多选模板列,我们需要新增一个单选模板列。
第一:模板列需要实现ITemplate 接口:定义用子控件填充模板化 ASP.NET 服务器控件的行为。子控件表示页上定义的内联模板。它包含一个重要的方法:InstantiateIn(Control container),ITemplate需要实现的方法当由类实现时,定义子控件和模板所属的 Control 对象。然后在内联模板中定义这些子控件。这里我们创建一个类:由于RadioButton会动态改变name值,所有这里直接生成html控件radio,这样可以保证name值都是一样的。
/// ITemplate :定义用子控件填充模板化
/// ASP.NET 服务器控件的行为。子控件表示页上定义的内联模板。
/// </summary>
public class RadioColumItemTemplate:ITemplate
{
/// <summary>
/// 单选按钮的ID
/// </summary>
public static string RadioButtonItemId
{
get
{
return "RadioColumnItem";
}
}
/// <summary>
/// ITemplate需要实现的方法
/// 当由类实现时,定义子控件和模板所属的 Control 对象。然后在内联模板中定义这些子控件。
/// </summary>
/// <param name="container"></param>
public void InstantiateIn(Control container)
{
HtmlGenericControl l = new HtmlGenericControl();
l.DataBinding += new EventHandler(l_DataBinding);
container.Controls.Add(l);
}
/// <summary>
/// 具体事件,添加单选按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void l_DataBinding(object sender, EventArgs e)
{
//加入html控件
HtmlGenericControl l = sender as HtmlGenericControl;
if (l != null)
{
GridViewRow row = (GridViewRow)l.NamingContainer;
l.InnerHtml = "<input type='radio' name='" + RadioButtonItemId + "' value='" + row.DataItemIndex + "'/>";
}
}
第二:我们需要对新增的单选模板列做些设置以及把它集成到GridView控件中去,这里最重要的就是重写GridView的CreateColumnEvent。在生成列的时候执行我们自定义的模板列。
{
Owner.CreateColumnEvent += new WebCustomControl_GridViewEx.CreateColumnHandler(Owner_CreateColumnEvent);
}
/// <summary>
/// 生成列事件
/// </summary>
/// <param name="col"></param>
void Owner_CreateColumnEvent(System.Collections.ICollection col)
{
ArrayList colList = col as ArrayList;
AddColumn(colList);
}
/// <summary>
/// 添加单选列
/// </summary>
/// <param name="col"></param>
void AddColumn(ArrayList col)
{
if (Visible)
{
TemplateField checkColumn = new TemplateField();
checkColumn.HeaderStyle.Width = this.Width;
checkColumn.ItemStyle.HorizontalAlign = HorizontalAlign.Center;
checkColumn.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
RadioColumItemTemplate cbItemTemplate = new RadioColumItemTemplate();
checkColumn.ItemTemplate = cbItemTemplate;
checkColumn.ItemStyle.Width = this.Width;
checkColumn.HeaderText = "单选列";
if (this.Align == CustomColumnAlign.Left)
{
col.Insert(0, checkColumn);
}
else if (this.Align == CustomColumnAlign.Right)
{
col.Add(checkColumn);
}
else if (this.Align == CustomColumnAlign.Custom)
{
col.Insert(this.Position, checkColumn);
}
}
}
第三:读取单选列被选中记录的主键值,控件中因为事先并不知道数据源结构,所以这里只返回数据行的索引值,后台需要根据这个索引值在数据源中查询相关数据。
/// 读取单选列的值
/// </summary>
/// <returns></returns>
public string GetRadioItemValue()
{
HttpRequest request = HttpContext.Current.Request;
return request.Form[RadioColumItemTemplate.RadioButtonItemId];
}
总结:扩展后控件单选效果的实现得到简化,无需程序员去手动添加模板列,以及实现客户端单选功能。后台取值也简化了。扩展服务器控件其实并不难,难的是你不去了解它。有时就是这样的小小封装对你平时的工作效率会有比较大的提高。一个人的成功有时往往体现在细节上。