ASP.NET GridView 內的 RadioButton 因每行產生獨立 name 屬性,瀏覽器無法自動強制單選,需透過 JavaScript 手動管理勾選狀態,並將選中行索引回傳伺服器端。
<asp:GridView ID="gvData" runat="server" AutoGenerateColumns="False" DataKeyNames="Id"
OnRowDataBound="gvData_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="選取">
<ItemTemplate>
<asp:RadioButton ID="rbSelect" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="名稱" />
<asp:BoundField DataField="Description" HeaderText="說明" />
</Columns>
</asp:GridView>
<asp:HiddenField ID="hfSelectedIndex" runat="server" />
protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var rb = (RadioButton)e.Row.FindControl("rbSelect");
if (rb != null)
{
// 傳入 ClientID 與 RowIndex
string script = $"setSingleSelect('{rb.ClientID}', {e.Row.RowIndex});";
rb.Attributes["onclick"] = script;
}
}
}
<script type="text/javascript">
function setSingleSelect(selectedId, rowIndex) {
// 1. 記錄選中行索引到 HiddenField
document.getElementById('<%= hfSelectedIndex.ClientID %>').value = rowIndex;
// 2. 取得 GridView 內所有 RadioButton
var grid = document.getElementById('<%= gvData.ClientID %>');
var inputs = grid.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type === 'radio') {
inputs[i].checked = (inputs[i].id === selectedId);
}
}
}
</script>
protected void btnConfirm_Click(object sender, EventArgs e)
{
int index = int.Parse(hfSelectedIndex.Value);
if (index >= 0 && index < gvData.Rows.Count)
{
string id = gvData.DataKeys[index].Value.ToString();
// 取得該行其他控件值
var row = gvData.Rows[index];
string name = ((Label)row.FindControl("lblName")).Text;
// 業務邏輯...
}
}
// 綁定在 GridView 載入完成後
$('#<%= gvData.ClientID %> input[type=radio]').on('click', function () {
$('#<%= hfSelectedIndex.ClientID %>').val($(this).closest('tr').index());
$('#<%= gvData.ClientID %> input[type=radio]').not(this).prop('checked', false);
});
| 方案 | 優點 | 缺點 |
|---|---|---|
| RadioButton + JS (本文) | 原生控制項、完整伺服器端事件支援 | 需手寫 JS 同步 name 屬性 |
| CheckBox + 單選邏輯 | 樣式易控制 | 語意不符、同樣需 JS |
| TemplateField 放 <input type=radio name=grp> | 瀏覽器原生單選、無需 JS | 伺服器端難取得選中值、無 PostBack 事件 |
| GridView Selection (SelectCommand) | 內建選取高亮、伺服器端 SelectedIndexChanged | 預設整行點選、樣式客製化受限 |
DataKeyNames 直接取得主鍵,避免隱藏欄位。UpdatePanel 時,JS 綁定需在 pageLoad 或 EndRequest 重新註冊。<label> 或 aria-label。