我在aspx页面上有一些分散的<p>
元素,我使用类似的类将它们组合在一起 - <p class="instructions" runat="server">
在我的代码背后,使用C#我想隐藏这些元素,使用类似的东西
instructions.Visible = false;
但是我知道如果我使用ID,我只能在代码隐藏中执行此操作,但这将导致无效的HTML / CSS选择器,因为您不能拥有具有相同ID名称的多个ID ...
或者是否有另一种方法来分组控件,如果不是按类分组?
编辑:我不能使用JavaScript,因此选择必须在C#codebehind / ASP.NET中完成答案 0 :(得分:19)
事情很简单。在你的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类设置其Visibility。 您只需调整标记,就不需要遍历控件集合的大量代码。
答案 1 :(得分:14)
除了在单个容器控件中对所有控件进行分组之外,在ASP.NET服务器端代码中给定一些属性没有简单的方法来查找一组控件。
在客户端,您可以使用jQuery之类的内容来查找这些元素并隐藏它们:
$(".instructions").hide();
我可能会在页面完全加载时做出响应:
$(document).ready(function() {
$(".instructions").hide();
});
在Javascript中隐藏元素的一个缺点是,如果有足够的数据,可能需要一秒钟,导致内容闪烁。另一个区别是隐藏内容客户端没有从DOM中删除它 - 内容就是隐藏的。隐藏控件服务器端可防止其内容被发送到HTML。
在C#中做同样的事情有点困难 - 它需要递归遍历控制树并在Control
集合中查找匹配的元素。这是一个很常见的操作,实用程序功能很有用。 C# iterator syntax(收益率回报)有助于实现这一目标:
// 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;
}
答案 2 :(得分:5)
我想回答第一个答案之一 - 我们使用递归来完成所有控件。首先,我们不应该对儿童用品进行递归吗?我没有仔细查看代码,发现我们一直在“c”上递归调用该方法,而不是“child”。其次,我发现我的网页上没有任何项目可以转换为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。
答案 3 :(得分:3)
如果您包含JQuery核心,您只需在页面上注册此脚本:
<script>
$(document).ready(function() {
$(".instructions").hide();
});
</script>
它使用JQuery类选择器http://api.jquery.com/class-selector/
答案 4 :(得分:1)
您可以创建一个递归函数来遍历页面控件数组,检查每个控件的CssClass属性并根据需要进行设置。
答案 5 :(得分:1)
<asp:Panel>
接近如果它们连续放在您的表单中,您可以将它们全部放入其中。这样,您可以轻松切换面板的.Visible属性以隐藏表单的块。
您可以使用ClientScriptManager.RegisterStartupScript()
发出JavaScript,然后使用jQuery按类隐藏。
答案 6 :(得分:1)
在塞巴斯蒂安P.R. Gingter解决方案的基础上,这就是我所做的,尽管考虑到我必须使用基于MS的WebControl而不是选择更简单的HTML控件,它仍然感觉有点黑客。
在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>
答案 7 :(得分:1)
我测试了blackcatweb的解决方案。它返回dublicates,所以我修复了它并为WebControls添加了方法。我的代码如下。要按类设置attrName =&#34; class&#34;:
/// <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;
}
}
答案 8 :(得分:-1)
您可以使用JQuery Class Name Selector来实现此目的。
另一个解决方案是保持相同的id而不是控制服务器端。在JavaScript中使用document.getElementById获取控件,在您的情况下,您将获得一个数组,该数组将保存具有相同ID的所有控件。迭代这些控件并相应地设置它们的显示属性。