2008-12-18 82 views
33

我得到了一個模板化的控件(一箇中繼器),它列出了一些文本和其他標記。每個項目都有一個與之相關聯的單選按鈕,使用戶可以選擇由中繼器創建的項目之一。ASP.NET RadioButton搞亂了名字(groupname)

中繼器寫入radiobutton設置其id和名稱生成的默認ASP.NET命名約定使每個單選按鈕充分'組'。這意味着所有的單選按鈕都是相互獨立的,這不幸意味着我可以同時選擇所有的單選按鈕。單選按鈕具有用於設置通用名稱的聰明屬性'groupname',因此它們被分組在一起,因此應該是相關的(因此我一次只能選擇一個)。問題是 - 這不起作用 - 中繼器確保id和名稱(控制分組)是不同的。

因爲我使用中繼器(可能是一個listview或任何其他模板化的數據綁定控件)我不能使用RadioButtonList。那麼,這離開我了嗎?

我知道我以前有過這個問題並解決了它。我知道幾乎每個ASP.NET程序員都必須擁有它,所以爲什麼我不能谷歌並找到解決問題的可靠解決方案?我遇到了解決方案來強制通過JavaScript(醜陋!)進行分組,甚至將單選按鈕作爲非服務器控件處理,迫使我執行Request.Form[name]來讀取狀態。我也嘗試過重寫PreRender事件上的name屬性 - 不幸的是,擁有的頁面和masterpage會覆蓋此名稱以反映完整的id /名稱,所以我最終得到了同樣錯誤的結果。

如果你沒有比我發佈的更好的解決方案,你仍然非常歡迎發表你的想法 - 至少我會知道我的朋友'傑克'是正確的是如何搞砸ASP.NET有時;)

+0

參見:* [BUG:單選按鈕並不相互排斥當在Repeater服務器控件使用(http://support.microsoft.com/default.aspx?scid=kb; EN-US; Q316495)*。這只是簡單的瘋狂......這是自1.0框架以來的一個錯誤,它具有如此巨大的影響力。我需要繼承單選按鈕並覆蓋一些方法以使其工作(用於我當前的ASP.NET版本)。是什麼賦予了? – 2008-12-18 13:32:55

回答

7

谷歌福:asp.net radiobutton repeater problem

事實上,ID的mangling的不幸後果。我的建議是創建一個 - 或者選擇一個可用的自定義控件,在客戶端添加對同名的支持。

+0

不幸的是你是對的,但它是如此的痛苦! – 2008-12-18 13:33:50

7

ASP.NET提示:在直放站

此使用單選按鈕控件是JavaScript函數的代碼:

function SetUniqueRadioButton(nameregex, current) 
{ 
    re = new RegExp(nameregex); 
    for(i = 0; i < document.forms[0].elements.length; i++) 
    { 
     elm = document.forms[0].elements[i] 
     if (elm.type == 'radio') 
     { 
     if (re.test(elm.name)) 
     { 
      elm.checked = false; 
     } 
     } 
    } 
    current.checked = true; 
} 

的代碼通過ItemDataBound事件鏈接到Repeater。爲了正常工作,您需要知道Repeater控件的名稱以及要分配給RadioButton的GroupName。在這種情況下,我使用rptPortfolios作爲中繼器的名稱,投資組合的組名:

protected void rptPortfolios_ItemDataBound(object sender, 
              RepeaterItemEventArgs e) 
{ 
    if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType 
     != ListItemType.AlternatingItem) 
     return; 

    RadioButton rdo = (RadioButton)e.Item.FindControl("rdoSelected"); 
    string script = 
     "SetUniqueRadioButton('rptPortfolios.*Portfolios',this)"; 
    rdo.Attributes.Add("onclick", script); 

} 

REF:http://www.codeguru.com/csharp/csharp/cs_controls/custom/article.php/c12371/

+0

偉大的解決方案!工作得很好。 – Ricketts 2012-05-15 03:34:24

4

弗拉基米爾·斯米爾諾夫已創建瞭解決此問題的一個偉大的自定義控件。我們在我們的項目中一直使用GroupRadioButton,並且它一直在使用中繼器內部創建的單選按鈕以及中繼器外部的單選按鈕完全工作,這些按鈕都屬於同一組。

0

這可能不是每個人的理想解決方案,但我做了以下使用jQuery。

<asp:RadioButton ID="rbtnButton1" groupName="Group1" runat="server" /> <asp:RadioButton ID="rbtnButton2" groupName="Group1" runat="server" />

etc...

然後在您的母版頁下面的代碼。 (或所有頁面)

$(function() { 
//This is a workaround for Microsoft's GroupName bug. 
//Set the radio button's groupName attribute to make it work. 
$('span[groupName] > input').click(function() { 
    var element = this; 
    var span = $(element).parent(); 
    if (element.checked) { 
     var groupName = $(span).attr('groupName'); 
     var inputs = $('span[groupName=' + groupName + '] > input') 
     inputs.each(function() { 
      if (element != this) 
       this.checked = false; 
     }); 
    } 
}); 

});

3

這可能是一個好一點..

我有一個用戶控件基本上是一組轉發器內的單選按鈕,用戶控件的每個實例有一個名爲FilterTitle公共財產,這是每個實例是唯一的。

這兩個屬性添加到您的單選按鈕,用自己的公共屬性名稱替換FilterTitle

onclick='<%# "$(\"input[name$=btngroup_" + FilterTitle + "]\").removeAttr(\"checked\"); $(this).attr(\"checked\",\"checked\");" %>' GroupName='<%# "btngroup_" + FilterTitle %>' 

更簡單..

onclick="$('input[name$=btngroup1]').removeAttr('checked'); $(this).attr('checked','checked');" GroupName="btngroup1" 
5

使用jQuery腳本:

<script type="text/javascript"> 
    function norm_radio_name() { 
     $("[type=radio]").each(function (i) { 
      var name = $(this).attr("name"); 
      var splitted = name.split("$"); 
      $(this).attr("name", splitted[splitted.length - 1]); 
     }); 
    }; 

    $(document).ready(function() { 
     norm_radio_name(); 
    }); 

    // for UpdatePannel 
    var prm = Sys.WebForms.PageRequestManager.getInstance(); 

    prm.add_endRequest(function() { 
     norm_radio_name(); 
    }); 
</script> 
+0

真棒解決方案! – 2011-08-30 07:33:27

+2

小心!如果使用此解決方案,則無法在代碼隱藏中處理用戶更改,因爲服務器預期的名稱/值對將永遠不會更改。 _i.e._在頁面加載過程中檢查/取消選中的任何內容都會在用戶操作後保持選中/取消選中狀態。 – 2011-12-07 07:56:39

1

我也被這個錯誤困擾,並決定放棄轉發器而轉向動態構建g內置控件的表格。在用戶控制或在網頁上,只需添加以下元素:

<asp:Table ID="theTable" runat="server"> 
    <asp:TableHeaderRow runat="server"> 
     <asp:TableHeaderCell runat="server" Text="Column 1"/> 
     <asp:TableHeaderCell runat="server" Text="Column 2"/> 
     <asp:TableHeaderCell runat="server" Text="Column 3"/> 
    </asp:TableHeaderRow> 
</asp:Table> 

然後在添加代碼以單選按鈕和其他所需的控制背後的數據行。當然你也可以做同樣的像DIV等元素:

<div runat="server" ID=theDiv"> 
</div> 

但我們還是希望能爲ASP.NET團隊來解決與中繼器和列表視圖解決這個不幸的問題。我仍然喜歡中繼控制,並儘可能使用它。

5

我知道這是一箇舊帖子,但這是我最終用listview做的。我的列表視圖綁定在VB代碼隱藏中,所以我不確定這是否適用於中繼器,但我想它可能是類似的。

我所做的是使用未選中任何其他單選按鈕的函數來處理單選按鈕的OnCheckChanged事件。然後,當我離開頁面時,我查找了選定的單選按鈕。

該解決方案避免了JavaScript和jQuery,並完全忽略GroupName問題。這並不理想,但它的功能與(我)預期的一樣。我希望這對其他人有幫助。

標記:

代碼:

Protected Sub rdbSelect_Changed(ByVal sender As Object, ByVal e As System.EventArgs) 

    Dim rb1 As RadioButton = CType(sender, RadioButton) 

    For Each row As ListViewItem In lvw.Items 
    Dim rb As RadioButton = row.FindControl("rdbSelect") 
     If rb IsNot Nothing AndAlso rb.Checked Then 
     rb.Checked = False 
     End If 
    Next 
    rb1.Checked = True 
End Sub 

,然後在提交按鈕被點擊:

Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click 

    For Each row As ListViewItem In lvw.Items 
    Dim rb As RadioButton = row.FindControl("rdbSelect") 
     Dim lbl As Label 
     If rb IsNot Nothing AndAlso rb.Checked = True Then 
      lbl = row.FindControl("StudentID") 
      Session("StudentID") = lbl.Text 
     End If 
    Next 

    Response.Redirect("~/TransferStudent.aspx") 
End Sub 
+0

不錯的解決方案!我一直在尋找一種不需要javascript的解決方案,並且從來沒有想過只是取消選中所有的單選按鈕OnCheckChanged。乾杯! – Curt 2011-08-02 13:33:02

2

下面是完整起見純JavaScript解決方案。

就在這個onclick屬性添加到您的RadioButton元素(與你的RadioButton的組名替代組名):

<asp:RadioButton ... GroupName="GroupName" onclick="SelectRadioButton('GroupName$',this)" ... /> 

,包括此Javascript在網頁:

<script type="text/javascript"> 
function SelectRadioButton(regexPattern, selectedRadioButton) 
    { 
     regex = new RegExp(regexPattern); 
     for (i = 0; i < document.forms[0].elements.length; i++) 
     { 
      element = document.forms[0].elements[i]; 
      if (element.type == 'radio' && regex.test(element.name)) 
      { 
       element.checked = false; 
      } 
     } 
     selectedRadioButton.checked = true; 
    } 
</script> 
2

創建自定義控件並覆蓋唯一ID到列表視圖UniqueID + GroupName

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

namespace MYCONTROLS 
{ 

[ToolboxData("<{0}:MYRADIOBUTTON runat=server></{0}:MYRADIOBUTTON >")] 
public class MYRADIOBUTTON : RadioButton 
{ 
    public override string UniqueID 
    { 
     get 
     { 
      string uid = base.UniqueID; 
      //Fix groupname in lisview 
      if (this.Parent is ListViewDataItem && GroupName != "") 
      { 
       uid = this.Parent.UniqueID; 
       uid = uid.Remove(uid.LastIndexOf('$')); 
       uid += "$" + GroupName; 

      } 
      return uid; 


     } 
    } 

} 
} 

這是一個繼承自RadioButton(公共類MYRADIOBUTTON:RadioButton)的自定義控件。 如果你在課堂上什麼都不做,你會得到一個正常的RadioButton。覆蓋UniqueId,您可以更改名稱屬性呈現方式的邏輯。 爲了保持頁面上其他控件的唯一名稱(在listview之外),您可以從ListView中獲取UniqueId並將GroupName添加到該控件中,並將其添加到RadioButton中。

這解決了在列表視圖中對不同行上的RadioButton進行分組的問題。你可能想要添加一些更多的屬性邏輯來打開/關閉這個功能,所以它的行爲就像一個普通的RadioButton。

+0

一些解釋你的代碼正在做什麼將有助於這個答案的未來讀者 – 2013-01-22 00:36:25

2

我知道這個問題有點老了,但我認爲這可能有助於某人,因此發佈我的解決方案,以解決這個問題。

這個問題有兩個部分:

  1. 爲了防止多個單選按鈕的選擇在同一時間。
  2. 瞭解在服務器端代碼中單擊了哪個單選按鈕。

我在Repeater中的單選按鈕有類似的問題。我在這裏找到部分解決方案: Simple fix for Radio Button controls in an ASP.NET Repeater using jQuery

請閱讀上面的文章以瞭解問題。我提到這篇文章,這是很好的幫助。如上所述,這個問題有兩個部分,一是防止一次選擇多個單選按鈕。其次,要知道在服務器端代碼中單擊了哪個單選按鈕。上面的文章中發佈的解決方案僅適用於第一部分。但是,在那裏寫的代碼以及在那裏發佈的解決方案的更新對我來說都不起作用。所以我不得不修改它以使其工作。這是我的解決方案。

我想用投票按鈕創建投票。我的單選按鈕(ID)的名稱是PollGroupValue,並將組名設置爲中繼器中的PollGroup。記住ASP.net中的Groupname屬性在生成的html中呈現爲name屬性。我的代碼如下:

<script type="text/javascript"> 

/* Step-01: */ 
$(document).ready(function() { 

    /* Step-02: */ 
    $("[name*='PollGroup']").each(function() { 
     $(this).attr('ci-name', $(this).attr('name')); 
    }); 

    /* Step-03: */ 
    $("[name*='PollGroup']").attr("name", $("[name*='PollGroup']").attr("name")); 

    $('#Poll1_BtnVote').click(function (e) { 

     /* Step - 04: */ 
     if ($("[name*='PollGroup']").filter(':checked').length == 0) { 
      alert('Please select an option.'); 
      e.preventDefault(); 
     } 

     /* Step - 05: */ 
     $("[name*='PollGroup']").each(function() { 
      $(this).attr('name', $(this).attr('ci-name')); 
     }); 
    }); 
}); 

步驟1: 每當一個單選按鈕在使用中繼器,它的組名被改變,因爲asp.net改變它,使之唯一。因此,每個單選按鈕都會得到不同的組名(客戶端生成的標記中的名稱屬性)。因此,用戶可以同時選擇所有選項。這個問題通過使用jquery代碼解決,正如隨後的評論所解釋的。

第2步: 該代碼塊創建一個名爲ci-name的新custome屬性,並將name屬性的原始值複製到此新的自定義屬性中。輪詢中的每個單選按鈕都會重複該過程。這一步將幫助我們在後面的步驟。

步驟3: 該代碼塊將poll中所有單選按鈕的名稱屬性值設置爲第一個單選按鈕的名稱屬性值。此步驟可防止用戶一次選擇多個選項。

第4步: 此代碼在投票按鈕點擊事件的事件處理程序中,檢查用戶是否檢查了至少一個選項。如果他沒有,則顯示錯誤消息。

第5步: 此代碼在投票按鈕點擊事件的事件處理程序中,將所有單選按鈕的名稱屬性的值設置爲其原始值。這是通過從自定義屬性ci-name複製值來實現的。這允許asp.net服務器端代碼知道哪個按鈕被實際點擊。

1

這是使用反射的純服務器端方法。 RadioButton控件使用UniqueGroupName屬性來確定組名稱。組名緩存在_uniqueGroupName字段中。通過使用反射設置此字段,我們可以覆蓋默認的組名,並使用中繼器中所有單選按鈕上相同的組名。請注意,此代碼必須在'RadioButton'控件的'PreRender'事件中運行,以確保新的羣組名稱在帖子後面保留。

protected void rbOption_PreRender(object sender, EventArgs e) 
{ 
    // Get the radio button. 
    RadioButton rbOption = (RadioButton) sender; 

    // Set the group name. 
    var groupNameField = typeof(RadioButton).GetField("_uniqueGroupName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 
    groupNameField.SetValue(rbOption, "MyGroupName"); 

    // Set the radio button to checked if it was selected at the last post back. 
    var groupValue = Request.Form["MyGroupName"]; 

    if(rbOption.Attributes["value"] == groupValue) 
    { 
     rbOption.Checked = true; 
    } 
} 

RadioButton源代碼:http://reflector.webtropy.com/default.aspx/Net/Net/[email protected]@[email protected]/DEVDIV/depot/DevDiv/releases/whidbey/netfxsp/ndp/fx/src/xsp/System/Web/UI/WebControls/[email protected]/2/[email protected]

0

自定義控制/置換以解決該HtmlInputControl.RenderAttributes()方法通過忽略RenderedNameAttribute屬性:

/// <summary> 
/// HACK: For Microsoft&apos;s bug whereby they mash-up value of the "name" attribute. 
/// </summary> 
public class NameFixHtmlInputRadioButton : HtmlInputRadioButton 
{ 
    protected override void RenderAttributes(HtmlTextWriter writer) 
    { 
     // BUG: Usage of 'HtmlInputControl.RenderedNameAttribute' 
     // writer.WriteAttribute("name", this.RenderedNameAttribute); 
     writer.WriteAttribute(@"name", Attributes[@"Name"]); 

     Attributes.Remove(@"name"); 

     var flag = false; 
     var type = Type; 

     if (! string.IsNullOrEmpty(type)) 
     { 
      writer.WriteAttribute(@"type", type); 
      Attributes.Remove(@"type"); 
      flag = true; 
     } 

     base.RenderAttributes(writer); 

     if (flag && DesignMode) 
     { 
      Attributes.Add(@"type", type); 
     } 

     writer.Write(@" /"); 
    } 
} 
0

我用相同TECHNIC取消選中其它無線電與jquery請發現以下代碼

<asp:RadioButton ID="rbSelectShiptoShop" runat="server" onchange="UnCheckRadio(this);" CssClass="radioShop" /> 

和下面的腳本

function UnCheckRadio(obj) { 
      $('.radioShop input[type="radio"]').attr('checked', false); 
      $(obj).children().attr('checked', true); 
     }