web-dev-qa-db-ja.com

ASP.Net RadioButtonとCheckBoxがSpan内でレンダリングされるのはなぜですか?

私はこれを期待しています:

<asp:CheckBox    ID="CheckBox1"    runat="server" CssClass="myClass" />
<asp:RadioButton ID="RadioButton1" runat="server" CssClass="myClass" />
<asp:TextBox     ID="TextBox1"     runat="server" CssClass="myClass" />

...このようにレンダリングするには(簡単にするためにいくつかの属性を削除)

<input id="CheckBox1"    type="checkbox" class="myClass" />
<input id="RadioButton1" type="radio"    class="myClass" />
<input id="TextBox1"     type="text"     class="myClass" /> 

...実際には、RadioButtonCheckBoxspanタグでラップされ、CSSクラスがそこに適用されます。

<span class="myClass"><input id="CheckBox1"    type="checkbox" /></span> 
<span class="myClass"><input id="RadioButton1" type="radio"    /></span> 
<input type="text" id="TextBox1" class="myClass" /> 

これには理由があり、それを回避する方法はありますか? jQueryセレクターのすべてをキャッチすることができないため、jQueryセレクターは見苦しくなります。

$("input.myClass")

確かにそれは次のようになります:

$("input.myClass, span.myClass input")

...しかし、それはいです。独自のセレクターを作成することもできましたが、やはりエレガントではありませんでした。

52
Mark

System.Web.UI.WebControls名前空間のWebコントロールは、ブラウザーごとに異なるレンダリングを行う場合があります。常に同じ要素をレンダリングすることを期待することはできません。特定のブラウザで機能させるために必要と思われるものを追加する場合があります。

コントロールがhtmlとしてレンダリングされる方法を制御する場合は、代わりにSystem.Web.UI.HtmlControls名前空間のコントロールを使用する必要があります。あれは:

<input type="checkbox" id="CheckBox1" runat="server" class="myClass" />
<input type="radio" name="RadioButton1" runat="server" class="myClass" />
<input type="text" id="TextBox1" runat="server" class="myClass" />

対応するhtml要素としてレンダリングされ、追加の要素は追加されません。これはもちろん、コントロールがそうではないように、ブラウザーの互換性に責任を負う必要があることを意味します。また、これらのコントロールには、WebControls名前空間のコントロールのすべての機能がありません。

49
Guffa

InputAttributesプロパティが見つかるまで、これは私を夢中にさせていました。

たとえば、スパンナンセンスなしでチェックボックスコントロールにクラスを直接追加する方法は次のとおりです。

myCheckBoxControl.InputAttributes.Add("class", "myCheckBoxClass")
113
JohnFx

デフォルトでは、すべてのWebControlは<span>タグとしてレンダリングされ、さらにコントロール作成者が追加するカスタムレンダリングとしてレンダリングされます。

カスタムWebControlを作成するときに最初に行うことの1つは、「 TagKey 」プロパティをオーバーライドしてdivまたはスパン以外の何かをレンダリングすることです。このプロパティのデフォルト値はHtmlTextWriterTag.Spanです。

チェックボックス項目をサブクラス化し、TagKeyプロパティをオーバーライドして他の何かをレンダリングできますが、すべてのチェックボックスを独自のバージョンにする必要があります。

5
womp

私はこの問題に遭遇し、制御アダプターを使用してそれを解決しようとしました。

ラジオボタンリストに対してこれを行う例については、 here を参照してください。

私はRadioButtonAdaptor-としてこれで終わった

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.Adapters;

public class RadioButtonAdapter : WebControlAdapter
{
    protected override void Render(HtmlTextWriter writer)
    {
        RadioButton targetControl = this.Control as RadioButton;

        if (targetControl == null)
        {
            base.Render(writer);

            return;
        }

        writer.WriteBeginTag("input");
        writer.WriteAttribute("type", "radio");
        writer.WriteAttribute("name", targetControl.GroupName);
        writer.WriteAttribute("id", targetControl.ClientID);            

        if (targetControl.CssClass.Length > 0)
        {
            writer.WriteAttribute("class", targetControl.CssClass);
        }      

        writer.Write(" />");

    }
}

そして、これは私のブラウザファイルに追加されました-

<browser refID="Default">
        <controlAdapters>            
            <adapter controlType="System.Web.UI.WebControls.RadioButton"
               adapterType="RadioButtonAdapter" />
        </controlAdapters>
</browser>

もちろん、これにはいくつかの欠点があります。 上記のリンク で言及されているものに加えて、すべてを暗示しないと機能も失われます(上記のコードではラジオボタンをチェックできません)。 CSSに優しいコントロールアダプターがいくつかありますが、ラジオボタンコントロールはカバーしていません。 Reflectorを使用して、デフォルトのコントロールアダプターを開始点として取得できる場合があります。

3
Spongeboy

プレーンなRadioButtonは、しばしばスパンなしでレンダリングされます。 CssClass、Style、Enabledプロパティを設定すると、RadioButtonはスパンでレンダリングされます。クライアント側のスクリプトでラジオボタンを操作する必要がある場合、この不整合は大きな痛みです。私が通常行うことは、ダミーCssClassを適用して、常に一貫してスパンをレンダリングすることです。

1
Li Chen

私が考える最良の方法はこれです:


    public class HtmlTextWriterNoSpan : HtmlTextWriter
    {
        public HtmlTextWriterNoSpan(TextWriter textWriter) : base(textWriter)
        { 
        }

        protected override bool OnTagRender(string name, HtmlTextWriterTag key)
        {
            if (name == HtmlTextWriterTag.Span)
            {
                return false;
            }

            return base.OnTagRender(name, key);
        }
    }

カスタムコントロールで使用するには:


    protected override void Render(HtmlTextWriter writer)
    {
        writer = new HtmlTextWriterNoSpan(writer);
        base.Render(writer);
        // HERE MORE CODE
    }
0
Jimmi

同様の問題を発見し、チェックボックスと親スパンを有効/無効にする簡単なjQueryベースの関数を作成しました

function resetChk(ctl, bEnable) { 

            if (bEnable){
                ctl.removeAttr('disabled').parent().removeAttr('disabled');
            }else{
                ctl.attr('disabled', true).parent().attr('disabled', true);
            }

        }
0
Stas Svishov