首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET 2.0 資料教程:為 GridView 新增 RadioButton 列實現單選 (TemplateField + 群組名稱同步)

     編輯:關於ASP.NET

GridView 內建選取按鈕功能單一,若需單選列表 (如點選即顯示詳細資料),可加入 RadioButton 列。關鍵挑戰:HTML radio 需共用 name 屬性才能互斥,但 ASP.NET 控制項渲染時會產生唯一 ID,導致無法分組。本文示範 JavaScript 強制同步群組與伺服端取得選取值。

GridView 定義 RadioButton 列

<asp:GridView ID="gvProducts" runat="server" 
    DataSourceID="odsProducts" 
    AutoGenerateColumns="False"
    DataKeyNames="ProductID"
    OnRowDataBound="gvProducts_RowDataBound"
    OnSelectedIndexChanged="gvProducts_SelectedIndexChanged">

    <Columns>
        <asp:TemplateField HeaderText="選取">
            <ItemTemplate>
                <asp:RadioButton ID="rbSelect" runat="server" 
                    GroupName="ProductSelection" 
                    AutoPostBack="True" 
                    OnCheckedChanged="rbSelect_CheckedChanged" />
            </ItemTemplate>
        </asp:TemplateField>

        <asp:BoundField DataField="ProductID" HeaderText="ID" ReadOnly="True" />
        <asp:BoundField DataField="ProductName" HeaderText="產品名稱" />
        <asp:BoundField DataField="UnitPrice" HeaderText="單價" DataFormatString="{0:C2}" HtmlEncode="False" />
        <asp:BoundField DataField="CategoryName" HeaderText="類別" />
    </Columns>
</asp:GridView>

<asp:ObjectDataSource ID="odsProducts" runat="server" TypeName="BLL.ProductsBLL" SelectMethod="GetProducts" />

<hr />
<h3>選取的產品詳細資料</h3>
<asp:DetailsView ID="dvProductDetail" runat="server" 
    AutoGenerateRows="False" Visible="False">
    <Fields>
        <asp:BoundField DataField="ProductID" HeaderText="ID" />
        <asp:BoundField DataField="ProductName" HeaderText="名稱" />
        <asp:BoundField DataField="UnitPrice" HeaderText="單價" DataFormatString="{0:C2}" HtmlEncode="False" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="庫存" />
        <asp:BoundField DataField="CategoryName" HeaderText="類別" />
        <asp:BoundField DataField="SupplierName" HeaderText="供應商" />
    </Fields>
</asp:DetailsView>

RadioButton 群組名稱同步問題與解決

ASP.NET 渲染 RadioButton 時,GroupName 會作為 HTML name 屬性,但因每列在不同 NamingContainer 中,實際輸出的 name 可能為 ctl00$MainContent$gvProducts$ctl02$rbSelect 等,導致無法互斥。

方案一:JavaScript 強制單選 (推薦,支援 AutoPostBack)

<script type="text/javascript">
    function syncRadioButtons(clickedRb) {
        // 找到同群組的所有 RadioButton (透過 GroupName 末尾匹配)
        var groupSuffix = '_' + clickedRb.name.split('_').pop(); // 取得 rbSelect 部分
        var inputs = document.getElementsByTagName('input');
        for (var i = 0; i < inputs.length; i++) {
            if (inputs[i].type == 'radio' && inputs[i].name.endsWith(groupSuffix) && inputs[i] != clickedRb) {
                inputs[i].checked = false;
            }
        }
    }
</script>

protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        RadioButton rb = (RadioButton)e.Row.FindControl("rbSelect");
        // 注入 onclick 呼叫同步函式
        rb.Attributes["onclick"] = "syncRadioButtons(this);";
        
        // 可選:高亮選中列
        if (rb.Checked) e.Row.CssClass = "selected-row";
    }
}

方案二:使用原生 HTML input radio (無 AutoPostBack,配合按鈕提交)

<ItemTemplate>
    <input type="radio" name="ProductSelection" value='<%# Eval("ProductID") %>' 
           onclick="this.form.__EVENTTARGET.value=''; this.form.__EVENTARGUMENT.value='';" />
</ItemTemplate>

<asp:Button ID="btnViewDetail" runat="server" Text="檢視詳細" OnClick="btnViewDetail_Click" />

protected void btnViewDetail_Click(object sender, EventArgs e)
{
    string selectedID = Request.Form["ProductSelection"];
    if (!string.IsNullOrEmpty(selectedID))
    {
        dvProductDetail.DataSource = new BLL.ProductsBLL().GetProductByID(int.Parse(selectedID));
        dvProductDetail.DataBind();
        dvProductDetail.Visible = true;
    }
}

伺服端取得選取值並顯示詳細資料

protected void rbSelect_CheckedChanged(object sender, EventArgs e)
{
    RadioButton rb = (RadioButton)sender;
    if (rb.Checked)
    {
        GridViewRow row = (GridViewRow)rb.NamingContainer;
        int productID = (int)gvProducts.DataKeys[row.RowIndex].Value;
        
        dvProductDetail.DataSource = new BLL.ProductsBLL().GetProductByID(productID);
        dvProductDetail.DataBind();
        dvProductDetail.Visible = true;
        
        // 高亮選中列
        foreach (GridViewRow r in gvProducts.Rows) r.CssClass = "";
        row.CssClass = "selected-row";
    }
}

CSS 樣式:高亮選中列

<style>
    .selected-row { background-color: #ffffcc !important; }
    .selected-row td { border-top: 2px solid #ffcc00; border-bottom: 2px solid #ffcc00; }
</style>

分頁情境:跨頁單選狀態保持

RadioButton 單選天然不需跨頁保持 (同時間只能選一項),但若需記住使用者上次選取:

private int? LastSelectedProductID
{
    get { return ViewState["LastSelectedProductID"] as int?; }
    set { ViewState["LastSelectedProductID"] = value; }
}

protected void gvProducts_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    gvProducts.PageIndex = e.NewPageIndex;
    gvProducts.DataBind();
    
    // 還原選中狀態 (若選中項在當前頁)
    if (LastSelectedProductID.HasValue)
    {
        foreach (GridViewRow row in gvProducts.Rows)
        {
            if ((int)gvProducts.DataKeys[row.RowIndex].Value == LastSelectedProductID.Value)
            {
                RadioButton rb = (RadioButton)row.FindControl("rbSelect");
                rb.Checked = true;
                rbSelect_CheckedChanged(rb, EventArgs.Empty); // 觸發詳細資料載入
                break;
            }
        }
    }
}

protected void rbSelect_CheckedChanged(object sender, EventArgs e)
{
    RadioButton rb = (RadioButton)sender;
    if (rb.Checked)
    {
        GridViewRow row = (GridViewRow)rb.NamingContainer;
        int productID = (int)gvProducts.DataKeys[row.RowIndex].Value;
        LastSelectedProductID = productID;
        // ... 載入詳細資料
    }
}

比較:RadioButton vs CommandField Select

特性TemplateField RadioButtonCommandField SelectButton
視覺呈現圓形單選按鈕,直觀連結/按鈕文字「選取」
互斥邏輯需 JS/原生 input 修正框架自動處理 (SelectedIndex)
AutoPostBack支援 (需 JS 同步)內建 PostBack
取得選取值DataKeys[RowIndex] 或 Request.FormSelectedDataKey / SelectedIndex
樣式客製高 (CSS/JS 完全控制)中 (ControlStyle/RowStyle)

結語

GridView RadioButton 列雖需額外 JavaScript 修正群組名稱,但提供更直觀的單選體驗。關鍵技巧:GroupName 設定、RowDataBound 注入 onclick 同步函式、CheckedChanged 取得 DataKey 載入詳細資料。現代專案建議改用客戶端框架 (Vue/React/Blazor) 管理選取狀態,或採用原生 input type="radio" 配合按鈕提交,簡化伺服端邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved