2008-12-18 26 views
33

Tôi có một điều khiển templated (một bộ lặp) liệt kê một số văn bản và đánh dấu khác. Mỗi mục có một radio kết hợp với nó, làm cho người dùng có thể chọn MỘT trong số các mục được tạo bởi bộ lặp.ASP.NET RadioButton gây rối với tên (tên nhóm)

Bộ lặp lại ghi thiết lập nút radio tên và id được tạo bằng quy ước đặt tên mặc định của ASP.NET làm cho mỗi nút vô tuyến thành một nhóm 'đầy đủ'. Điều này có nghĩa là tất cả các radiobutton độc lập với nhau, điều này lại không may có nghĩa là tôi có thể chọn tất cả các nút radio cùng một lúc. Các radiobutton có thuộc tính thông minh 'groupname' được sử dụng để thiết lập một tên chung, do đó, họ nhận được nhóm lại với nhau và do đó nên được phụ thuộc (vì vậy tôi chỉ có thể chọn một tại một thời điểm). Vấn đề là - điều này không hoạt động - bộ lặp sẽ đảm bảo id và do đó tên (điều khiển nhóm) khác nhau.

Vì tôi sử dụng bộ lặp (có thể là một listview hoặc bất kỳ điều khiển databound templound khác) Tôi không thể sử dụng RadioButtonList. Vậy điều đó để lại cho tôi ở đâu?

Tôi biết tôi đã gặp vấn đề này trước và giải quyết vấn đề. Tôi biết hầu như tất cả các lập trình ASP.NET phải có nó quá, vậy tại sao tôi không thể google và tìm một giải pháp vững chắc cho vấn đề này? Tôi đã xem xét các giải pháp để thực thi việc nhóm theo JavaScript (xấu xí!) Hoặc thậm chí để xử lý các nút vô tuyến như các điều khiển không phải máy chủ, buộc tôi phải thực hiện một số Request.Form[name] để đọc trạng thái. Tôi cũng đã thử nghiệm ghi đè thuộc tính tên trên sự kiện PreRender - tiếc là trang sở hữu và trang chính lại ghi đè tên này để phản ánh id/tên đầy đủ, vì vậy tôi kết thúc với cùng một kết quả sai.

Nếu bạn không có giải pháp tốt hơn so với những gì tôi đăng, bạn vẫn rất hoan nghênh để đăng suy nghĩ của bạn - ít nhất tôi sẽ biết rằng người bạn của tôi 'jack' là đúng về làm thế nào messed lên ASP.NET đôi khi;)

+0

Xem: * [BUG: Radio Buttons Are Not loại trừ lẫn nhau Khi sử dụng trong một Repeater Server Control] (http://support.microsoft.com/default.aspx?scid=kb; en-us; Q316495) *. Điều đó chỉ đơn giản là điên rồ ... Đó là một lỗi từ khuôn khổ 1.0, và nó có tác động lớn như vậy. Tôi cần phải kế thừa radiobutton và ghi đè lên một vài phương pháp để làm cho nó hoạt động (cho phiên bản ASP.NET hiện tại của tôi). Đưa cái gì? –

Trả lời

7

Google-fu: asp.net radiobutton repeater problem

Thật vậy, hậu quả không may của việc mang theo id. Việc của tôi sẽ tạo một - hoặc chọn một trong nhiều điều khiển tùy chỉnh có sẵn để thêm hỗ trợ cho cùng một tên trên máy khách.

+0

Thật không may bạn đúng, nhưng đó là một nỗi đau! –

7

ASP.NET Mẹo: Sử dụng RadioButton Controls trong một Repeater

Đây là mã cho hàm 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; 
} 

Mã này được liên kết với Repeater thông qua sự kiện ItemDataBound. Để nó hoạt động đúng, bạn cần phải biết tên của điều khiển Repeater, cũng như GroupName bạn đang gán cho RadioButton. Trong trường hợp này, tôi đang sử dụng rptPortfolios như tên của Repeater, và Danh mục đầu tư như tên nhóm:

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

Giải pháp tuyệt vời! Hoạt động rất tốt. – Ricketts

4

Vladimir Smirnov đã tạo một điều khiển tùy chỉnh tuyệt vời mà giải quyết vấn đề này . Chúng tôi đã sử dụng GroupRadioButton trong các dự án của chúng tôi và nó đã hoạt động hoàn hảo với các nút radio được tạo bên trong bộ lặp và các nút khác ngoài bộ lặp lại tất cả là một phần của cùng một nhóm.

0

Đây có thể không phải là giải pháp lý tưởng cho mọi người, nhưng tôi đã làm như sau bằng cách sử dụng jQuery.

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

etc...

Sau đó, bao gồm đoạn mã sau vào trang chủ của bạn. (hoặc tất cả các trang của bạn)

$(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

Điều này có thể tốt hơn một chút ..

Tôi có một usercontrol trong đó chủ yếu là tập hợp các radiobutton bên trong một bộ lặp, mỗi trường hợp của usercontrol có một tài sản công cộng gọi FilterTitle, mà là duy nhất cho mỗi trường hợp.

thêm hai thuộc tính này để RadioButton bạn thay thế FilterTitle với tên tài sản công của riêng bạn

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

đơn giản hơn ..

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

tôi sử dụng jQuery kịch bản:

<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

+1 cho giải pháp tuyệt vời! –

+2

Hãy coi chừng! nếu bạn sử dụng giải pháp này, bạn sẽ không thể xử lý các thay đổi của người dùng trong codebehind vì các cặp tên/giá trị mà máy chủ mong đợi sẽ không bao giờ bị thay đổi. _i.e._ mọi thứ được chọn/bỏ chọn trong khi tải trang sẽ vẫn được chọn/bỏ chọn bất chấp hành động của người dùng. –

1

tôi cũng bị bối rối bởi lỗi này và đã quyết định chỉ thả bộ lặp lại có lợi cho việc xây dựng động g một bảng với các điều khiển bên trong. Trong kiểm soát của người dùng hoặc trên trang của bạn, chỉ cần thêm các yếu tố sau:

<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> 

Sau đó thêm hàng dữ liệu vào sau bằng nút radio và các điều khiển bắt buộc khác. Tất nhiên, bạn có thể làm tương tự với các yếu tố khác như DIV:

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

Nhưng chúng tôi vẫn hy vọng nhóm ASP.NET sẽ khắc phục vấn đề đáng tiếc này với chế độ xem lặp lại và danh sách. Tôi vẫn thích điều khiển lặp lại và sử dụng nó bất cứ khi nào có thể.

5

Tôi biết đây là một bài đăng cũ, nhưng dưới đây là những gì tôi đã làm với chế độ xem danh sách. Listview của tôi là ràng buộc trong codebehind VB, vì vậy tôi không chắc chắn nếu điều này sẽ làm việc tốt với một repeater, nhưng tôi tưởng tượng nó có thể là tương tự.

Điều tôi đã làm là xử lý sự kiện OnCheckChanged của các nút vô tuyến với chức năng đã bỏ chọn bất kỳ nút radio nào khác. Sau đó, tôi đã tìm nút radio đã chọn khi tôi điều hướng khỏi trang.

Giải pháp này tránh JavaScript và jQuery và bỏ qua hoàn toàn vấn đề GroupName. Nó không lý tưởng, nhưng nó hoạt động như (I) mong đợi. Tôi hy vọng nó hữu ích cho người khác.

Markup:

Code:

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 

Và sau đó khi vào nút Submit được nhấp:

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

Giải pháp tuyệt vời! Tôi đã tìm kiếm một giải pháp mà không yêu cầu javascript và không bao giờ nghĩ đến việc chỉ cần bỏ chọn tất cả các radiobutton 'OnCheckChanged'. Chúc mừng! – Curt

2

Dưới đây là một giải pháp javascript thuần túy vì lợi ích của sự hoàn chỉnh.

Chỉ cần thêm onclick thuộc tính này để tố RadioButton của bạn (thay thế GroupName với GroupName RadioButton của bạn):

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

Và bao gồm javascript này trong trang của bạn:

<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

Tạo Kiểm soát tùy chỉnh và ghi đè UniqueID vào chế độ xem danh sách 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; 


     } 
    } 

} 
} 

Đó là một điều khiển tùy chỉnh kế thừa từ RadioButton (lớp công khai MYRADIOBUTTON: RadioButton). Nếu bạn không làm gì trong lớp, bạn sẽ có RadioButton bình thường. Ghi đè UniqueId, bạn có thể thay đổi logic để biết thuộc tính name được hiển thị như thế nào. Để vẫn giữ tên duy nhất cho các điều khiển khác trên trang (bên ngoài listview), bạn có thể lấy UniqueId từ ListView và thêm GroupName vào đó và thêm nó vào RadioButton.

Điều này khắc phục sự cố với nhóm RadioButton trên các hàng khác nhau trong chế độ xem danh sách. Bạn có thể muốn thêm một số logic hơn với một thuộc tính để bật/tắt tính năng này để nó hoạt động giống như một RadioButton bình thường.

+0

Một số giải thích về những gì mã của bạn đang làm sẽ hữu ích cho độc giả tương lai của câu trả lời này –

+0

dòng đầu tiên của mình Tạo điều khiển tùy chỉnh và ghi đè UniqueID vào listview UniqueID + GroupName –

2

Tôi biết câu hỏi này là hơi cũ, nhưng tôi nghĩ rằng nó có thể giúp ai đó, do đó gửi bài giải pháp của tôi cho vấn đề này.

Vấn đề này có 2 phần:

  1. Để tránh lựa chọn nhiều hơn một nút radio tại một thời điểm.
  2. Để biết nút radio nào đã được nhấp vào trong mã phía máy chủ.

Tôi gặp sự cố tương tự với nút radio trong bộ lặp. Tôi tìm thấy một phần giải pháp ở đây: Simple fix for Radio Button controls in an ASP.NET Repeater using jQuery

Vui lòng đọc bài viết trên để hiểu sự cố. Tôi đã giới thiệu bài viết này và nó đã giúp ích rất nhiều. Như đã đề cập ở trên, vấn đề này có hai phần, đầu tiên là ngăn chặn việc chọn nhiều nút radio cùng một lúc. Thứ hai, để biết nút radio nào đã được nhấp vào trong mã phía máy chủ. Các giải pháp được đăng trong bài viết trên làm việc cho tôi chỉ cho phần đầu tiên. Tuy nhiên mã được viết ở đó cũng như các bản cập nhật cho giải pháp được đăng ở đó không có tác dụng đối với tôi. Vì vậy, tôi đã phải sửa đổi nó một chút để làm cho nó hoạt động. Đây là giải pháp của tôi.

Tôi muốn tạo cuộc thăm dò ý kiến ​​bằng nút Bỏ phiếu. Tên nút radio của tôi (ID) là PollGroupValue với Groupname được đặt thành PollGroup trong bộ lặp. Ghi thuộc tính Groupname trong ASP.net được hiển thị dưới dạng thuộc tính name trong html được tạo. Mã của tôi là như sau:

<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')); 
     }); 
    }); 
}); 

Bước 1: Bất cứ khi nào một nút radio được sử dụng trong repeater, groupname của nó bị thay đổi, kể từ asp.net thay đổi nó để làm cho nó độc đáo. Do đó, mỗi nút radio sẽ nhận được tên nhóm khác nhau (thuộc tính name trong đánh dấu được tạo phía máy khách). Do đó, người dùng có thể chọn tất cả các tùy chọn cùng một lúc. Vấn đề này được giải quyết bằng cách sử dụng mã jquery như được giải thích bởi các bình luận tiếp theo.

Bước 2: Khối mã này tạo thuộc tính custome mới được gọi là ci-name và sao chép giá trị gốc của thuộc tính name vào thuộc tính tùy chỉnh mới này.Quá trình này lặp lại cho mọi nút radio trong cuộc thăm dò ý kiến. Bước này sẽ giúp chúng tôi trong bước sau.

Bước 3: Khối mã này đặt giá trị thuộc tính tên của tất cả các nút radio trong cuộc thăm dò thành giá trị thuộc tính tên của nút radio đầu tiên. Bước này ngăn người dùng chọn nhiều tùy chọn cùng một lúc.

Bước 4: Mã này bên trong trình xử lý sự kiện của sự kiện nhấp nút biểu quyết, kiểm tra xem người dùng đã chọn ít nhất một tùy chọn hay chưa. Nếu không, thông báo lỗi sẽ hiển thị.

Bước 5: Mã này bên trong trình xử lý sự kiện của sự kiện nhấp nút, đặt giá trị thuộc tính tên của tất cả các nút radio thành giá trị ban đầu của chúng. Điều này đạt được bằng cách sao chép giá trị từ thuộc tính tùy chỉnh ci-name. Điều này cho phép mã phía máy chủ asp.net biết nút nào thực sự được nhấp.

1

Đây là phương pháp tiếp cận bên máy chủ thuần túy khi sử dụng phản chiếu. Điều khiển RadioButton sử dụng thuộc tính UniqueGroupName để xác định tên nhóm. Tên nhóm được lưu trong trường _uniqueGroupName. Bằng cách thiết lập trường này bằng cách sử dụng sự phản chiếu, chúng ta có thể ghi đè tên nhóm mặc định và sử dụng tên nhóm giống nhau trên tất cả các nút radio trong bộ lặp. Xin lưu ý mã này phải được chạy trong sự kiện 'PreRender' của điều khiển 'RadioButton' để đảm bảo tên nhóm mới được duy trì trên toàn bộ bài đăng. đang

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 nguồn: 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

Tôi có chính xác rằng việc này sẽ ngăn ASP.NET quan sát trạng thái 'Checked' của RadioButton, và bạn sẽ cần phải kiểm tra' Request.Form' theo cách thủ công cho trạng thái của nó? –

0

Một điều khiển tùy chỉnh/ghi đè để làm việc xung quanh phương pháp HtmlInputControl.RenderAttributes() bằng cách bỏ qua các RenderedNameAttribute tài sản:

/// <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

tôi đã sử dụng cùng một Technic để bỏ chọn đài phát thanh khác với jquery vui lòng tìm bên dưới mã

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

và kịch bản dưới đây

function UnCheckRadio(obj) { 
      $('.radioShop input[type="radio"]').attr('checked', false); 
      $(obj).children().attr('checked', true); 
     } 
Các vấn đề liên quan