Aspxページにいくつかの<p>
要素が散在しており、そのようなクラスを使用してグループ化しています-<p class="instructions" runat="server">
私のコードビハインドでは、C#を使用して、instructions.Visible = false;
のようなものを使用してこれらの要素を非表示にします
ただし、IDを使用する場合にのみコードビハインドでこれを実行できますが、同じID名を持つ複数のIDを持つことができないため、無効なHTML/CSSセレクターになります...
あるいは、クラスごとではない場合、コントロールをグループ化する別の方法はありますか?
編集:JavaScriptを使用できないため、選択はC#codebehind /ASP.NETで行う必要があります
すべてのコントロールを単一のコンテナーコントロールにグループ化する以外に、ASP.NETサーバー側コードでいくつかのプロパティが指定されたコントロールのグループを見つける簡単な方法はありません。
クライアント側では、 jQuery のようなものを使用して、これらの要素を見つけて非表示にすることができます。
$(".instructions").hide();
ページが完全に読み込まれたときに、おそらくこれを実行します。
$(document).ready(function() {
$(".instructions").hide();
});
Javascriptで要素を非表示にすることの欠点の1つは、十分なデータがある場合、1秒かかり、コンテンツがちらつく可能性があることです。もう1つの違いは、コンテンツをクライアント側で非表示にしても、DOMから削除されないことです。コンテンツは非表示になっているだけです。コントロールをサーバー側で非表示にすると、コンテンツがHTMLに出力されるのを防ぐことができます。
C#で同じことを行うのは少し難しいです。これには、コントロールツリーを再帰的にトラバースし、一致するControl
コレクション内の要素を探す必要があります。これは、ユーティリティ関数が役立つ十分に一般的な操作です。 C#イテレータ構文 (yield return)は、これをクリーンにするのに役立ちます。
// utility method to recursively find controls matching a predicate
IEnumerable<Control> FindRecursive( Control c, Func<Control,bool> predicate )
{
if( predicate( c ) )
yield return c;
foreach( var child in c.Controls )
{
if( predicate( c ) )
yield return c;
}
foreach( var child in c.Controls )
foreach( var match in FindRecursive( c, predicate ) )
yield return match;
}
// use the utility method to find matching controls...
FindRecursive( Page, c => (c is WebControl) &&
((WebControl)c).CssClass == "instructions" );
コントロールを非表示にするのは比較的簡単です。
foreach( WebControl c in FindRecursive( Page, c => (c is WebControl) &&
((WebControl)c).CssClass == "instructions" ) )
{
c.Visible = false;
}
とても簡単です。 ASPXの場合:
<p class="instructions" runat="server" OnPreRender="Paragraph_PreRender">
コードビハインド:
protected void Paragraph_PreRender(object sender; EventArgs e)
{
Control paragraph = (Control)sender;
paragraph.Visible = !paragraph.CssClass.Contains("instructions");
}
コードビハインドは、クラスのPreRenderイベントハンドラーに自動的に接続されます。これにより、送信者がコントロールにキャストされ、その可視性がcssクラスに依存するように設定されます。タグを調整するだけで、コントロールコレクションをトラバースする多くのコードは必要ありません。
最初の答えの1つに応答したいと思います。ここでは、再帰を使用してすべてのコントロールを実行しています。まず、子アイテムを繰り返してはいけませんか?コードを詳しく調べなかったので、「子」ではなく「c」でメソッドを再帰的に呼び出し続けていることがわかりました。次に、自分のWebページのどのアイテムもWebControlにキャストできず、HtmlGenericControlにのみキャストできることがわかりました。
編集後、私はこれを持っていました:
// utility method to recursively find controls matching a predicate
IEnumerable<Control> FindRecursive( Control c, Func<Control,bool> predicate )
{
if( predicate( c ) )
yield return c;
foreach (var child in c.Controls) {
if (predicate((Control)child)) {
yield return (Control)child;
}
}
foreach( var child in c.Controls )
foreach( var match in FindRecursive( (Control)child, predicate ) )
yield return match;
}
foreach (Control c in FindRecursive(Page, c => (c is HtmlGenericControl) &&
((HtmlGenericControl)c).Attributes["ishidden"] == "1"))
{
c.Visible = false;
}
「CssClass」を使用できなかったことに注意してください。これを機能させるには、独自の属性(「ishidden」)を設定する必要がありました。
<div runat="server" ishidden="1"> ... </div>
ASP.NET Framework 2.0/3.0 /3.5を使用しています。
JQueryコアを含める場合は、このスクリプトをページに登録するだけです。
<script>
$(document).ready(function() {
$(".instructions").hide();
});
</script>
JQueryクラスセレクターを使用します http://api.jquery.com/class-selector/
各コントロールのCssClass属性を確認し、必要に応じて設定して、ページコントロール配列をウォークする再帰関数を作成できます。
<asp:Panel>
_アプローチそれらがあなたのフォームに連続して配置される場合、あなたはそれらをすべて中に入れることができます。これにより、パネルの.Visibleプロパティを簡単に切り替えて、フォームのチャンクを非表示にできます。
ClientScriptManager.RegisterStartupScript()
を使用してJavaScriptを発行し、jQueryを使用してクラスで非表示にすることができます。
Sebastian P.R. Gingterソリューションに基づいて、これが私が行ったことですが、より単純なHTMLコントロールをオプトアウトする代わりに、MSベースのWebControlを使用する必要があることを考えると、まだ少しハックを感じます。
C#の場合:
protected void Paragraph_PreRender(object sender, EventArgs e)
{
WebControl paragraph = (WebControl)sender;
paragraph.Visible = !paragraph.CssClass.Contains("instructions");
}
Aspxの場合:
<asp:Label ID="Label1" CssClass="instructions" runat="server" Text="Label" onPreRender="Paragraph_PreRender"></asp:Label>
Blackcatwebのソリューションをテストしました。重複を返すので、修正してWebControlsのメソッドを追加しました。私のコードは以下の通りです。クラスセットattrName = "class"で検索するには:
/// <summary>
/// Find controls
/// </summary>
/// <param name="c">Control</param>
/// <param name="predicate">Function</param>
/// <returns>Control's</returns>
public static IEnumerable<Control> FindRecursive(Control c, Func<Control, bool> predicate)
{
if (predicate(c))
{
yield return c;
}
foreach (Control child in c.Controls)
{
foreach (Control founded in FindRecursive(child, predicate))
{
yield return founded;
}
}
}
/// <summary>
/// Find WebControls by attr
/// </summary>
/// <param name="c">Control</param>
/// <returns>WebControls</returns>
public static IEnumerable<WebControl> FindWebControlsByAttr(Control baseControl, string attrName, string attrValue)
{
foreach (WebControl c in FindRecursive(baseControl, c => (c is WebControl)
&& !string.IsNullOrEmpty(((WebControl)c).Attributes[attrName])
&& ((WebControl)c).Attributes[attrName].Contains(attrValue)))
{
yield return c;
}
}
/// <summary>
/// Find HtmlGenericControls by attr
/// </summary>
/// <param name="c">Control</param>
/// <returns>HtmlGenericControls</returns>
public static IEnumerable<HtmlGenericControl> FindControlsByAttr(Control baseControl, string attrName, string attrValue)
{
foreach (HtmlGenericControl c in FindRecursive(baseControl, c => (c is HtmlGenericControl)
&& !string.IsNullOrEmpty(((HtmlGenericControl)c).Attributes[attrName])
&& ((HtmlGenericControl)c).Attributes[attrName].Contains(attrValue)))
{
yield return c;
}
}
この目的のために JQuery Class Name Selector を使用できます。
別の解決策は、同じIDを維持し、コントロールをサーバー側にしないことです。 JavaScriptでは、document.getElementByIdを使用してコントロールを取得します。この場合、同じIDを持つすべてのコントロールを保持する配列を取得します。これらのコントロールを繰り返し、それに応じて表示属性を設定します。