我可以阻止.NET吃ID吗?

时间:2008-09-02 08:09:24

标签: c# .net javascript html css

我现在是一名信息架构师和JavaScript开发人员,但最近我又重新开始进行后端编码。而且,在尝试将HTML原型集成并与我们基于C#的CMS一起工作时,我发现我们的程序员对.NET ID任意重写的HTML ID属性表示不满。

我可以理解.NET更改ID的代码隐藏推理,但在尝试开发时,您无法再使用ID jQuery增强的接口引起了一些摩擦。我该怎么做才能解决这个问题?

我尝试过使用class属性,但这真的很糟糕,不是它的意思,也没有解决.NET有效改变渲染源的问题。这也意味着CSS现在不太有用,创建和维护效率也会降低。

任何提示或建议都非常感谢 - 任何一些不那么不眠之夜...

10 个答案:

答案 0 :(得分:25)

简短的回答是否定的,对于webforms,id总是可以根据元素的嵌套重写。您可以通过ClientID属性访问id,因此您可以将id设置为页面/控件末尾的脚本中的变量,然后将它们放入jQuery中。

类似的东西:

<asp:button id="ImAButton" runat="server">Click Me</asp:button>

<script type="text/javascript">
var buttonId = "<%=ImAButton.ClientId%>";
$("#"+buttonId).bind('click', function() { alert('hi); });
</script>

这是我知道的黑客,但它会奏效。 (我应该注意未启动的,我在那里使用原型$ get by id方法)

答案 1 :(得分:12)

一种方法是手动覆盖ID:

public override string UniqueID
{
  get { return this.ID; }
}
public override string ClientID
{
  get { return this.ID; }
}

Rick Strahl wrote a blog post提供了有关该方法的更多信息。

答案 2 :(得分:7)

查看ASP.Net MVC - 它解决了ASP.Net默认生成的过度杀死对象层次结构。

这个网站是用MVC编写的(我认为) - 看看它的结构。如果我现在正在开展一个新项目,我会先考虑它

如果您遇到基本的ASP.Net,请小心覆盖ClientID和UniqueID - 它往往会破坏许多Web控件。

我发现的最好方法是将不可读的ClientID传递给Javascript。

答案 3 :(得分:4)

您可以扩展.net控件,并在调用相关属性时使它们返回实际ID。

ClientID是id属性,UniqueID是html元素的name属性。因此,当您创建如下所示的文本框并使用此文本框而不是框架中的文本框时,您将使id和name属性呈现为与服务器端ID相同。

public class MyTextBox : TextBox
{
    public override string ClientID { get { return ID; } }
    public override string UniqueID { get { return ID; } }
}

要使用这个新的用户控件,基本上就像对自定义用户控件一样注册此控件(您可以在web.config中执行,因此您不必在所有页面中执行此操作):

<%@ Register Assembly="MyLibrary" NameSpace="MyLibrary.WebControls" TagPrefix="MyPrefix" %>

使用它就像使用文本框一样:

<MyPrefix:MyTextBox ID="sampleTextBox" runat="server" />

答案 4 :(得分:1)

就我个人而言,我使用了一组方法来为桥接服务器端的ASP.NET“魔术”(我还没有使用MS MVC的东西)和我的客户端代码,因为它的重叠发生的ID。以下只是一个可能有用或可能无用的内容:

public void RegisterControlClientID(Control control)
{
   string variableDeclaration = string.Format("var {0} = \"{1}\";", control.ID, control.ClientID);
   ClientScript.RegisterClientScriptBlock(GetType(), control.ID, variableDeclaration, true);
}

因此,在您的服务器端代码中,您只需调用它并传入要为其使用友好名称的控件实例。换句话说,在设计时期间,您可能有一个ID为“m_SomeTextBox”的文本框,并且您希望能够使用相同的名称编写JavaScript - 您只需在您的服务器端代码:

RegisterControlClientID(m_SomeTextBox);

然后在客户端上呈现以下内容:

var m_SomeTextBox = "ctl00_m_ContentPlaceHolder_m_SomeTextBox";

这样,您的所有JavaScript代码都可能完全不了解ASP.NET决定命名变量的内容。当然,这有一些注意事项,例如当你在页面上有多个控件实例时(例如,因为使用多个用户控件实例,所有实例都有m_SomeTextBox),但通常这种方法可能对您最基本的需求有用。

答案 5 :(得分:1)

我通常做的是创建一个接收字段名称的通用函数。它添加了通常的“asp.net”前缀并返回对象。

var elemPrefix = 'ctl00-ContentPlaceHolder-'; //replace the dashes for underscores

var o = function(name)
{    
    return document.getElementById(elemPrefix + name)
}

有了这个,你可以在jQuery中使用这种调用

$(o('buttonId')).bind('click', function() { alert('hi); });

答案 6 :(得分:1)

您绝对不希望将asp.net生成的ID硬编码到CSS中,因为如果您以控制树更改的方式重新排列页面上的内容,它可能会更改。

CSS ID确实存在,所以我会忽略只使用类的建议。

这里描述的各种javascript hacks对于一个小问题来说是过度杀伤。所以继承自一个类并重写ID属性。当你想要做的只是重构一些CSS时,建议切换到MVC当然没有帮助。

只需要使用CSS定位单独的div和span。如果要使用ID,请不要直接定位ASP.NET控件。

  <div id="DataGridContainer">
     <asp:datagrid runat=server id="DataGrid" >
         ......
     <asp:datagrid>
  </div>

答案 7 :(得分:0)

如果您正在使用jQuery,那么您可以使用CSS selectors and jQuery custome selectors加载来定位页面上的元素。因此,不是通过它的id选择提交按钮,而是可以执行以下操作:

$('fieldset > input[type="submit"]').click(function() {...});

答案 8 :(得分:0)

我可以看到.NET系统感觉不那么直观,但给它一个机会。根据我的经验,它最终会创建更清晰的代码。确定

<asp:button id="ImAButton" runat="server">Click Me</asp:button>

<script type="text/javascript">
var buttonId = <%=ImAButton.ClientId%>
$(buttonId).bind('click', function() { alert('hi); });
</script>

工作正常。但这是因为没有模块化。你真正想要的是这样的:

<script type="text/javascript">
function MakeAClick(inid)
{
  $(inid).bind('click', function() { alert('hi); });
}
</script>

然后在Java端或C#端使用您的代码调用MakeAClick。当然在C#方面它更有意义,你只需要ClientID。

这可能是您正在审核的代码的真正问题。

答案 9 :(得分:0)

更好的方法是使用ClientIDMode并将其设置为static。您甚至可以在特定页面中设置它,也可以在web.config文件中全局设置它。然后你再也不必处理这个问题了,你的JQuery更清洁了。

返回页首:

<%@ Page Title="" ClientIDMode="Static" Language="C#" CodeBehind="..." Inherits="WebApplication1.WebForm2"  %>

仅限控件:

<asp:Panel runat="server"  ClientIDMode="Static"></asp:Panel>