web-dev-qa-db-ja.com

ASP.NET RadioButtonが名前(グループ名)を乱している

いくつかのテキストと他のマークアップをリストするテンプレート化されたコントロール(リピーター)を取得しました。各アイテムにはラジオボタンが関連付けられているため、ユーザーはリピーターによって作成されたアイテムの1つを選択できます。

リピーターは、デフォルトのASP.NET命名規則で生成されたIDと名前を設定するラジオボタンを書き込み、各ラジオボタンを完全な「グループ」にします。これは、すべてのラジオボタンが互いに独立していることを意味します。これは、残念ながら、すべてのラジオボタンを同時に選択できることを意味します。ラジオボタンには、共通名を設定するために使用される巧妙な属性「groupname」があるため、グループ化され、依存する必要があります(したがって、一度に1つしか選択できません)。問題は-これが機能しない-リピーターがIDを確認し、したがって(グループ化を制御する)名前が異なることを確認することです。

私はリピーターを使用しているため(リストビューまたはその他のテンプレート化されたデータバインドコントロールである可能性があります)、RadioButtonListを使用できません。それでは、どこに私を残しますか?

私は以前にこの問題に遭遇してそれを解決したことがあるのを知っています。私はほとんどすべてのASP.NETプログラマーもそれを持っているに違いないことを知っています。 JavaScriptによるグループ化を強制する(醜い!)か、ラジオボタンを非サーバーコントロールとして処理するためのソリューションに出くわし、Request.Form[name]でステータスを読み取ります。また、PreRenderイベントのname属性をオーバーライドしてみました-残念ながら、所有するページとマスターページがこの名前をオーバーライドして、完全なID /名前を反映しているため、同じ間違った結果になります。

あなたが私が投稿したものより良い解決策がない場合でも、あなたの考えを投稿することは大歓迎です-少なくとも私は友達の「ジャック」がASP.NETがいかに台無しになっているかについて正しいことを知っています;)

Google-fu: asp.netラジオボタンリピーターの問題

確かに、IDマングリングの不幸な結果です。私の見解は、クライアントに同じ名前のサポートを追加する-または利用可能な多くのカスタムコントロールの1つを選択することです。

7

ASP.NETヒント:リピーターでのRadioButtonコントロールの使用

これは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コントロールの名前と、RadioButtonに割り当てているGroupNameを知っている必要があります。この例では、リピーターの名前としてrptPortfoliosを使用し、グループ名としてPortfoliosを使用しています。

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/

8
Sheryar Nizar

ウラジミール・スミルノフは、この問題を解決する優れたカスタムコントロールをすでに作成しています。私たちはプロジェクトで GroupRadioButton を使用しており、リピーターの内部で作成されたラジオボタンとリピーターの外部で作成されたラジオボタンがすべて同じグループの一部であることで完全に機能しています。

6
Chris Magnuson

私は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>
6

私はこれが古い投稿であることを知っていますが、これが私がリストビューでやったことです。私のリストビューはVBコードビハインドでバインドされているので、これがリピーターでうまく機能するかどうかはわかりませんが、似ていると思います。

私がしたことは、ラジオボタンのOnCheckChangedイベントを、他のラジオボタンの選択を解除する関数で処理することでした。次に、ページから移動したときに、選択したラジオボタンを探しました。

このソリューションはJavaScriptとjQueryを回避し、GroupNameの問題を完全に無視します。理想的ではありませんが、(I)期待どおりに機能します。他の方々のお役に立てれば幸いです。

マークアップ:

<asp:ListView ID="lvw" runat="server">
  <LayoutTemplate>`
    <table>
      <th>Radio</th>
      <tr id="itemPlaceholder"></tr>
    </table>
  </LayoutTemplate>
  <ItemTemplate>
    <tr>
      <td><asp:RadioButton ID="rdbSelect" runat="server" AutoPostBack="true"
           OnCheckedChanged="rdbSelect_Changed"/></td>
    </tr>
  </ItemTemplate>
</asp:ListView>

コード:

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
5
Kit Z. Fox

以下は、完全を期すための純粋なJavaScriptソリューションです。

このonclick属性をRadioButton要素に追加するだけです(GroupNameRadioButtonのGroupNameに置き換えます):

<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>
3
Saeb Amini

これは少し良いかもしれません。

私は本質的にリピーター内のラジオボタンのセットであるユーザーコントロールを持っています。ユーザーコントロールの各インスタンスには、インスタンスごとに一意であるFilterTitleと呼ばれるパブリックプロパティがあります。

これら2つのプロパティをラジオボタンに追加して、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"
3
tbilly

私はこの質問が少し古いことを知っていますが、誰かに役立つかもしれないと思うので、この問題の私の解決策を投稿します。

この問題には2つの部分があります。

  1. 一度に複数のラジオボタンが選択されるのを防ぐため。
  2. サーバー側のコードでどのラジオボタンがクリックされたかを知るため。

リピーターのラジオボタンにも同様の問題がありました。私はここに部分的な解決策を見つけました: jQueryを使用したASP.NETリピーターのラジオボタンコントロールの簡単な修正

問題の理解を得るために上記の記事を読んでください。私はこの記事を参照しました、そしてそれは良い助けでした。上記のように、この問題には2つの部分があります。1つ目は、一度に複数のラジオボタンを選択できないようにすることです。次に、サーバー側のコードでクリックされたラジオボタンを確認します。上記の記事に投稿された解決策は、最初の部分でのみ機能しました。しかし、そこに書かれたコードとそこに投稿されたソリューションの更新は私にとってはうまくいきませんでした。そのため、機能させるために少し変更する必要がありました。これが私の解決策です。

投票ボタンで投票を作成したかった。ラジオボタン(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という新しいカスタム属性を作成し、name属性の元の値をこの新しいカスタム属性にコピーします。このプロセスは、投票中のすべてのラジオボタンに対して繰り返されます。このステップは、後のステップで役立ちます。

ステップ3:このコードブロックは、投票中のすべてのラジオボタンの名前属性の値を、最初のラジオボタンの名前属性の値に設定します。この手順により、ユーザーは一度に複数のオプションを選択できなくなります。

手順4:投票ボタンのクリックイベントのイベントハンドラー内のこのコードは、ユーザーが少なくとも1つのオプションをチェックしたかどうかを確認します。そうでない場合は、エラーメッセージが表示されます。

手順5:投票ボタンクリックイベントのイベントハンドラー内のこのコードは、すべてのラジオボタンの名前属性の値を元の値に設定します。これは、カスタム属性ci-nameから値をコピーすることによって実現されます。これにより、asp.netサーバー側のコードは、実際にクリックされたボタンを知ることができます。

2
yatz

カスタムコントロールを作成し、UniqueIDをリストビューの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をオーバーライドすると、name属性のレンダリング方法のロジックを変更できます。ページの他のコントロール(リストビュー以外)に一意の名前を維持するには、ListViewからUniqueIdを取得し、それにGroupNameを追加してRadioButtonに追加します。

これにより、リストビューのさまざまな行のRadioButtonをグループ化する際の問題が修正されます。通常のRadioButtonのように動作するように、この機能をオン/オフにするプロパティを使用してロジックを追加したい場合があります。

2
Mårten Holm

私もこのバグに困惑し、内部にコントロールがあるテーブルを動的に構築するためにリピーターをドロップすることにしました。ユーザーコントロールまたはページで、次の要素を追加するだけです。

<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チームがリピーターとリストビューに関するこの不幸な問題を修正するために回避できることを願っています。私はまだリピーターコントロールが好きで、可能な限りそれを使用します。

1
Lars Fastrup

これは、リフレクションを使用した純粋なサーバー側のアプローチです。 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/3@5@50727@3053/DEVDIV/depot/DevDiv/releases/whidbey/netfxsp/ndp/fx/src/xsp/System/Web/UI/WebControls/RadioButton @ cs/2/RadioButton @ cs

1
ACOMIT001

同じテクニックを使用して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);
       }
0
Ankit

これはすべての人にとって理想的なソリューションとは限りませんが、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;
        });
    }
});

});

0
helios456

RenderedNameAttributeプロパティを無視してHtmlInputControl.RenderAttributes()メソッドを回避するカスタムコントロール/オーバーライド:

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