扩展GridView之添加单选列

      背景:实现GridView的单选列,传统的做法应该是新增模板列,然后添加RadioButton,客户端实现单选,后台遍历读取选中行数据。


      第一:添加模板列,加入RadioButton。为了取值方便,我把记录的主键放在HiddenField中保存。

<asp:TemplateField meta:resourcekey="TemplateFieldResource3">
     
<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)"。这样可以实现单选的效果。

function rbCheck(obj)
{
  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的选中情况来取最后的记录的主键值。

/// <summary>
    
/// 取选中行的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值都是一样的。

/// <summary>
    
/// 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。在生成列的时候执行我们自定义的模板列。

if (Owner != null&&Visible)
{
   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>
        
/// 读取单选列的值
        
/// </summary>
        
/// <returns></returns>
        public string GetRadioItemValue()
        {
            HttpRequest request 
= HttpContext.Current.Request;
            
return request.Form[RadioColumItemTemplate.RadioButtonItemId];
        }

       

      总结:扩展后控件单选效果的实现得到简化,无需程序员去手动添加模板列,以及实现客户端单选功能。后台取值也简化了。扩展服务器控件其实并不难,难的是你不去了解它。有时就是这样的小小封装对你平时的工作效率会有比较大的提高。一个人的成功有时往往体现在细节上。


 

原文地址:https://www.cnblogs.com/ASPNET2008/p/1441163.html