【问题标题】:Can I stop .NET eating IDs?我可以停止 .NET 吃 ID 吗?
【发布时间】:2010-09-07 12:41:38
【问题描述】:

我现在是一名信息架构师和 JavaScript 开发人员,但最近我又回到了后端编码领域。而且,在尝试集成 HTML 原型并与我们基于 C# 的 CMS 一起工作时,我与我们的程序员就 .NET 任意重写表单元素的 HTML ID 属性发生了争执。

我可以理解 .NET 更改 ID 的代码隐藏推理,但事实上您在尝试开发时不能再使用 ID,例如jQuery 增强接口引起了一些摩擦。我可以做些什么来解决这个问题?

我尝试使用 class 属性,但这真的很糟糕,不是它的意思,也没有解决 .NET 有效地动态更改渲染源的问题。这也意味着 CSS 现在没那么有用了,创建和维护的效率也越来越低。

任何提示或建议都非常感谢 - 任何不眠之夜的东西......

【问题讨论】:

    标签: c# .net javascript html css


    【解决方案1】:

    您可以扩展 .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" />
    

    【讨论】:

    • 您还需要一个用于列表框控件的适配器和一个 .browser 文件
    【解决方案2】:

    简短的回答是否定的,对于网络表单,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>
    

    我知道这是一个 hack,但它会起作用。 (我应该注意对于未启动的,我在那里使用 Prototype $ get by id 方法)

    【讨论】:

    • 当然,您需要在该服务器标签周围加上引号。而且我不明白为什么这是一个黑客行为。这是我一直使用的合法技术。这就是服务器标签和 ClientID 之类的东西。
    • 我想它只是感觉像一个黑客,因为它很乱。我更希望它们成为 javascript 可以与之对话的控件上的静态、可预测 id
    • 我也一直使用这种方法。我通常在 head 标记中(在独立页面上)或在 asp:Content 控件中声明我的所有“动态”变量,该控件写入 master 的 head 标记中的 asp:ContentPlaceHolder。这至少将包含动态 ID 的所有变量保留在一个位置。
    • Glenn,我在 buttonId 文字中添加了引号,并在 jquery 选择器中添加了一个“#”,以便 100% 正确:)。
    【解决方案3】:

    一种方法是手动覆盖 ID:

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      我发现的最佳方法是将无法读取的 ClientID 传递给 Javascript。

      【讨论】:

        【解决方案5】:

        就我个人而言,我使用我开发的一组方法来桥接服务器端 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 的实例),但通常这种方法可能对您最基本的需求有用。

        【讨论】:

          【解决方案6】:

          我通常做的是创建一个接收字段名称的通用函数。它添加通常的“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); });
          

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              【解决方案8】:

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

              你说得对,CSS ID 有自己的位置,所以我会忽略只使用类的建议。

              这里描述的各种 javascript hack 对于一个小问题来说太过分了。从类继承并覆盖 ID 属性也是如此。当您只想重构一些 CSS 时,建议切换到 MVC 肯定没有帮助。

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

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

              【讨论】:

                【解决方案9】:

                我可以看到 .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。

                也许这是您正在审查的代码的真正问题。

                【讨论】:

                  【解决方案10】:

                  更好的方法是使用 ClientIDMode 并将其设置为 static。您甚至可以在 web.config 文件中为特定页面或全局设置它。这样您就不必再处理这个问题,并且您的 JQuery 更加干净。

                  页面顶部:

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

                  仅限控制:

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-19
                    • 2014-09-21
                    • 2021-12-29
                    • 2018-10-24
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多