如何在ASP.NET中按类而不是ID选择元素?
我在aspx页面上有一些分散的
元素,我使用类似的类将它们组合在一起 –
在我的代码背后,使用C#我想隐藏这些元素,使用像instructions.Visible = false;
但是我知道如果我使用ID,我只能在代码隐藏中执行此操作,但这会导致无效的HTML / CSS选择器,因为您不能拥有具有相同ID名称的多个ID …
或者是否有其他方法来分组控件,如果不是按类?
编辑:我不能使用JavaScript,因此选择必须在C#codebehind / ASP.NET中完成
除了在单个容器控件中对所有控件进行分组之外,在ASP.NET服务器端代码中给定一些属性没有简单的方法来查找一组控件。
在客户端,您可以使用类似jQuery的东西来查找这些元素并隐藏它们:
$(".instructions").hide();
我可能会在页面完全加载时执行此操作:
$(document).ready(function() { $(".instructions").hide(); });
在Javascript中隐藏元素的一个缺点是,如果有足够的数据,它可能需要一秒钟,并导致内容闪烁。 另一个区别是隐藏内容客户端不会将其从DOM中删除 – 内容只是隐藏。 隐藏控件服务器端可防止其内容被发送到HTML。
在C#中做同样的事情有点困难 – 它需要递归遍历控制树并在Control
集合中查找匹配的元素。 这是一个很常见的操作,实用程序function很有用。 C#iterator语法 (yield return)有助于使其干净:
// utility method to recursively find controls matching a predicate IEnumerable FindRecursive( Control c, Func 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中:
在你的代码隐藏中:
protected void Paragraph_PreRender(object sender; EventArgs e) { Control paragraph = (Control)sender; paragraph.Visible = !paragraph.CssClass.Contains("instructions"); }
代码隐藏将自动连接到类中的PreRender事件处理程序。 这会将发件人强制转换为控件,并根据css类设置其Visibility。 您只需调整标记,就不需要遍历控件集合的大量代码。
我想回答第一个答案之一 – 我们使用递归来完成所有控件。 首先,我们不应该对子项进行递归吗? 我没有仔细查看代码,发现我们一直在“c”上递归调用该方法,而不是“child”。 其次,我发现我的网页上没有任何项目可以转换为WebControl – 仅限于HtmlGenericControl。
编辑后,我有这个:
// utility method to recursively find controls matching a predicate IEnumerable FindRecursive( Control c, Func 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’)来实现此function。
...
我正在使用ASP.NET framework 2.0 / 3.0 / 3.5。
如果您包含JQuery核心,您只需在页面上注册此脚本:
它使用JQuery类选择器http://api.jquery.com/class-selector/
您可以创建一个递归函数来遍历页面控件数组,检查每个控件的CssClass属性并根据需要进行设置。
方法
如果它们连续放在您的表单中,您可以将它们全部放入其中。 这样,您可以轻松切换面板的.Visible属性以隐藏表单的块。
JavaScript方法
您可以使用ClientScriptManager.RegisterStartupScript()
发出JavaScript,然后使用jQuery按类隐藏。
我测试了blackcatweb的解决方案。 它返回dublicates,所以我修复了它并为WebControls添加了方法。 我的代码如下。 要按类set attrName =“class”进行搜索:
/// /// Find controls /// /// Control /// Function /// Control's public static IEnumerable FindRecursive(Control c, Func predicate) { if (predicate(c)) { yield return c; } foreach (Control child in c.Controls) { foreach (Control founded in FindRecursive(child, predicate)) { yield return founded; } } } /// /// Find WebControls by attr /// /// Control /// WebControls public static IEnumerable 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; } } /// /// Find HtmlGenericControls by attr /// /// Control /// HtmlGenericControls public static IEnumerable 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类名称选择器来实现此目的。
另一个解决方案是保持相同的id而不是控制服务器端。 在JavaScript中使用document.getElementById获取控件,在您的情况下,您将获得一个数组,该数组将保存具有相同ID的所有控件。 迭代这些控件并相应地设置其显示属性。
在塞巴斯蒂安PR Gingter解决方案的基础上,这就是我所做的,虽然考虑到我必须使用基于MS的WebControl而不是选择更简单的HTML控件,它仍然感觉有点黑客。
在C#中:
protected void Paragraph_PreRender(object sender, EventArgs e) { WebControl paragraph = (WebControl)sender; paragraph.Visible = !paragraph.CssClass.Contains("instructions"); }
在aspx中: