如何停止ASP.NET更改ID以便使用jQuery

53
我在网页上有一个标签控件。
<asp:Label ID="Label1" runat="server" Text="test"></asp:Label>

当页面被渲染时,该控件的ID会更改为类似于这样的内容

  <span id="ctl00_ContentPlaceHolder1_Label3">test</span>

我如何阻止ASP.NET更改ID以执行类似于以下jQuery操作的操作

$('#label1').html(xml);

其他答案已经展示了各种解决方案,以应对ASP.Net令人恼火的坚持创建自己的客户端ID的事实。虽然这并不能解决您目前的问题,但我最近读到,这将是ASP.Net 4.0今年晚些时候推出的功能之一。想必您会感兴趣。 - Saqib
4
FYI,这个功能将在ASP.NET 4.0中推出(可以控制服务器控件的客户端ID)。 - Rex M
20个回答

52

简短回答:

ClientIDMode="Static"设置。

<asp:Label ID="myLabel" ClientIDMode="Static" runat="server" Text="testing"></asp:Label>

较长的答案:

.NET 4现在可以让您选择您的ClientIDMode

类型:System.Web.UI.ClientIDMode
一个指示如何生成ClientID属性的值。

AutoID
ClientID的值是通过将每个父命名容器的ID值与控件的ID值连接而成。在数据绑定方案中,如果呈现了多个控件实例,则会在控件的ID值前插入递增值。每个段由下划线字符(_)分隔。此算法用于早于ASP.NET 4版本的ASP.NET。

Static
ClientID的值设置为ID属性的值。如果控件是命名容器,则该控件用作其包含的任何控件的命名容器层次结构的顶部。

Predictable
此算法用于位于数据绑定控件中的控件。ClientID的值是通过将父命名容器的ClientID值与控件的ID值连接而成。如果控件是生成多个行的数据绑定控件,则在末尾添加ClientIDRowSuffix属性中指定的数据字段的值。对于GridView控件,可以指定多个数据字段。如果ClientIDRowSuffix属性为空,则在末尾添加一个连续的编号,而不是数据字段值。此数字从零开始,并逐行递增1。每个段由下划线字符(_)分隔。

Inherit
控件继承其命名容器控件的ClientIDMode设置。这是默认值。


4
换句话说,使用静态模式强制ASP不更改ID。 - SoliQuiD
这是最好的答案。 - John Baker

42

不要使用这个选择器

$('#Label1')

使用这个,基本上你正在使用经典的ASP内联服务器端代码。

$('#<%= Label1.ClientID %>')

这将插入任何生成的ID作为文本。

如果你想要使用外部文件,我建议你创建一个全局的obj来保存所有客户端ID,并在你的外部文件中引用该obj(虽然不是最理想的解决方案,但也是一种解决方法)。

var MyClientIDs = {
    Label1 = '<%= Label1.ClientID %>',
    Label2 = '<%= Label2.ClientID %>',
    Textbox1 = '<%= Textbox1.ClientID %>',
    Textbox2 = '<%= Textbox2.ClientID %>'
};

然后在你的外部文件中,你可以访问Label1,例如:$('#' + MyClientIDs.Label1)


7
问题在于它不能用于外部JavaScript文件中。 - Andreas Grech
函数:function getLabel1Id() { return '#<%= Label1.ClientID %>'; } - 如果将其放置在aspx文件中,您可以从js文件中调用它。 - Tamas Czinege
9
抱歉,我认为这不是一个好的解决方案,因为它会阻止使用外部 JS 文件,而使用外部 JS 文件是最佳实践。 - Kenan Banks
1
它还有一个陷阱 - 一旦您将该服务器标签放入页面中,如果尝试添加动态控件,则会出现异常。 - James Orr
1
@Triptych 我同意... 解决办法之一是创建一个全局对象,该对象在页面上,这将使您能够访问所有客户端ID。我会更新答案并提供示例。 - Jon Erickson
使用asp.net 4.0,@user2622042 的下面的答案是最简单和最清晰的(除非您在重复器或类似设备中)。https://dev59.com/x3RB5IYBdhLWcg3w1Khe#19109742 这里是一个很好的参考 https://weblog.west-wind.com/posts/2009/Nov/07/ClientIDMode-in-ASPNET-40 - MemeDeveloper

27
在.NET 4+中设置ClientIDMode="Static"。这将解决您的问题。
示例:
<asp:Label ID="Label1" ClientIDMode="Static" runat="server" Text="test"></asp:Label>

20

你无法阻止 asp.net 生成这些ID,因为这就是它的工作方式。

你仍然可以这样使用jquery:

$('#<%=label1.ClientID %>').html(xml) 
或者
$('[id$=_label1]').html(xml)

1
在.NET 4中,你可以通过设置ClientIDMode属性的值来阻止asp.net生成这些ID:https://dev59.com/questions/x3RB5IYBdhLWcg3w1Khe#8428188。 - David d C e Freitas

17
如果且仅当您的容器布局永远不会更改,并且您需要将JavaScript/jQuery放在外部文件中时,您可以在jQuery选择器中使用生成的ID,即:
$('#ctl00_ContentPlaceHolder1_Label3').html(xml);

显然,这种方法需要你找出生成的ID,并且如果你开始更改站点/应用程序结构,需要谨慎处理。
否则,您最好的选择是:
1. 使用内联服务器端代码标记。这种方法的缺点是您无法将js代码放在外部文件中 -
$('#<%= Label3.ClientID %>').html(xml);

2. 在需要在 jQuery 中使用的每个控件上定义唯一的 CSS 类,这仍然允许您将 js 代码放在外部文件中 -


<asp:Label ID="Label3" runat="server" Text="test" CssClass="label3">
</asp:Label>

$('.label3').html(xml);

3. 使用jQuery选择器进行模式匹配原始ID,这将允许您将js代码放入外部文件中 -

$('[id$=Label3]').html(xml);

这个jQuery选择器将选择所有属性为id且值以Label3结尾的元素。我唯一能看到的潜在问题是,理论上可能会在主页面和两个内容页面中拥有id为Label3的Label控件。在这个例子中,使用上面的jQuery选择器将匹配所有三个标签,这可能会产生不希望出现的后果。
编辑:
我认为提醒您注意IDOverride控件可能会很有用。 示例页面可以在这里找到 它允许您指定哪些控件应该在输出的HTML标记中具有其混淆的id被覆盖为在渲染HTML页面时在.aspx文件中给定的id。我只是简单地使用了一个主页和面板玩过它,但它似乎工作得很好。使用这个,你可以在你的jQuery选择器中使用原始的id。然而,请注意,如果您在组合呈现一个页面的主页面和内容页面中具有相同的id控件,则结果是不可预测的。

非常好的回答。我认为使用jQuery可以使占位符之类的东西过时,但您完整而权威地回答了实际问题! - Mike
IDOverride的页面似乎已经消失了。我在网上四处搜寻,但找不到它。有人在任何地方发布了副本吗?我有一个简单的网站可以从中受益匪浅,而且我现在没有等待ASP.Net 4.0或学习MVC的能力。 - Steve Hiner

7

简短回答,不用担心使用asp.net的ID。在asp.net中,您可以向标签添加自己的属性:

<asp:TexBox ID="myTBox" runat="server" MyCustomAttr="foo" />

然后在 jQuery 中,您可以通过以下方式引用此元素:

$("input[MyCustomAttr='foo']")

我经常使用jQuery完成这个操作。希望能帮到你。

5
如果你在自定义属性前加上data-前缀,那么它就是有效的HTML5。 - Gabe Moothart

7
您可以使用类名来调用,而不是使用ID。
例如:
$('.CssClassName'). ...

如果您在MasterPage的第一行键入以下内容,您的控件ID将不会更改:

ClientIDMode="Static"

例如:
<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="Main_MasterPage" ClientIDMode="Static" %>

5

4

这里的大部分建议可能都可行,但是对jQuery代码的测试结果表明,纯ID选择器是迄今为止最快的。我经常使用以下这种方式:

$("[id$=origControlId]")

这段代码运行缓慢,但除非页面有很多控件和大量jQuery代码,否则问题不太明显。

由于将多个类分配给一个控件相当容易,您可以为每个控件赋予与其ID匹配的CSSClass。由于它们将是唯一的(您必须注意生成多个控件的重复类型控件),因此可以通过class进行选择。

例如:

<asp:Label ID="Label1" CssClass="Label1 SomeOtherClass" runat="server" Text="test">
</asp:Label>

可以通过以下方式唯一选择:

$(".Label1")

这个速度几乎和ID选择器一样快。

我从未考虑过这个:

$('#<%= Label1.ClientID %>')

但我会尝试它!


3
您需要将控件的ClientID传递给JavaScript代码(我怀疑Label1是否会被重命名为Label3)。
ClientScriptManager.RegisterClientScriptBlock(GetType(), "someKey", 
    "$('#" + Label1.ClientID + "').html(xml);", true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接