【问题标题】:ClientID of MenuItemMenuItem 的客户端 ID
【发布时间】:2011-12-08 06:29:22
【问题描述】:

我在页面上有一个项目,它有一系列 MenuItems(从数据库动态生成)作为菜单项。

每个 MenuItem 都将自己呈现为

<a class="ctl00_cphContent_cphMainContentTitle_uxHeaderMenu_menuPageNav_1 button ctl00_cphContent_cphMainContentTitle_uxHeaderMenu_menuPageNav_3" style="border-style:none;font-size:1em;" href="SomeURLHere.aspx">

但是,我想获取此链接的 ClientID(我们使用外部 Javascript 库在模态灯箱样式框架中弹出页面)。这样做的要求之一是我们需要识别“可点击对象 ID”,以便我们可以将其设置为能够在点击时触发事件。

我们网站上的其他任何地方

OurSite.SetupDialogueBoxForOpen('<%= HyperLink.ClientID =>');

但是由于某种原因,菜单项似乎没有分配给它的 ClientID 属性。这使得在 JavaScript 中设置客户端 ID 几乎是不可能的。

有谁知道如何获取菜单项的 ClientID(只是为了澄清菜单项的类型为 System.Web.UI.WebControls.MenuItem

提前致谢!

【问题讨论】:

标签: c# asp.net webforms menuitem


【解决方案1】:

如果您想更改控件中项目的呈现方式,可以使用StaticMenuItemTemplateDynamicMenuItemTemplate 属性。我只会在我的示例中使用第一个(静态,用于顶级项目):

<asp:Menu runat="server" ...>
  <StaticMenuItemTemplate>
    <a id="<%# GetSuitableClientId(Container) %>"><%# Eval("Text") %></a>
  </StaticMenuItemTemplate>
</asp:Menu>

StaticMenuItemTemplate 属性属于ITemplate 类型,并且通常使用此类模板属性,它使用TemplateContainer 属性进行修饰。这指定了要在其中实例化模板的容器,通常容器可以访问您在渲染中可能需要的某些上下文。在这种情况下,它是MenuItemTemplateContainer 类型,它实现了IDataContainer,因此可以访问数据项。

所以我们将这个容器传回页面中的一个方法,并在该方法中构造一个我们认为合适的 ID。例如,我们可以将数据项用于深度,将容器用于索引:

protected string GetSuitableClientId(MenuItemTemplateContainer container)
{
  MenuItem item = (MenuItem)container.DataItem;
  return String.Format("menuItem-{0}-{1}", item.Depth, container.ItemIndex);
}

我在构建此答案时的猜测是,您现在可以调整 JavaScript 以绑定到 &lt;a id="menuItem-2-4"&gt;Text&lt;/a&gt; 元素上的点击事件,因为您现在拥有可预测的客户端 ID。

编辑:您还可以在模板中使用以下内容,让 ASP.NET 负责创建唯一的客户端 ID,但这不太可预测...

<asp:HyperLink ID="MenuItem" runat="server" NavigateUrl='<%# Eval("NavigateUrl") %>' />

【讨论】:

    【解决方案2】:

    如何获取 DOM 中每个锚标记的列表并遍历它们查看 .class 直到找到 class=="whatever_Nav_ID_or_flag_you_entered_or_somehow_can_tell_this_element_apart" 然后使用 .id 为其分配一个 id?类似于:未经测试

    var anchors = document.getElementsByTagName("a");
    for(int i = 0; i < anchors.length()){
        if(anchors[i].class=="testClass"){
            anchors[i].id = "targetThisAnchor";
            break;
        }
    }
    

    编辑: 在渲染期间,您可以使用条件来查看新菜单项是否是您要查找的菜单项?

    <%
      if (MenuItem.flag == menuItemToTarget)
      {
          //set MenuItem id
      }
    %>
    

    【讨论】:

    • 这是一个好主意,理论上可行,但很多代码取决于在文档准备好之前知道 ID,即发送到浏览器的内容,所以我认为它必须是在 .NET 方面完成。
    【解决方案3】:

    试试这个,改selector $("menu &gt; a").bind('click',function(){}));

    【讨论】:

    • 恐怕有大约 10-15 个菜单项,我希望绑定到它唯一的一个,所以不能这样做:|
    【解决方案4】:

    你会像这样进入菜单项:

    OurSite.SetupDialogueBoxForOpen('<%= uxHeaderMenu.FindControl("menuPageNav_3").ClientID %>');
    

    由于您没有发布任何代码,我无法告诉您如何具体选择第三个(在上述情况下)....但这应该可以。

    您需要使用 FindControl,因为 MenuItem 是 Menu 的子项,而不是 Page 或用户控件的子项。

    【讨论】:

    • 通常这适用于其他控件,但是 menuPageNav_3(或任何可能被调用的)仍然不会有 ClinentID 调用。 uxHeaderMenu 将是 MainMenu,FindControl 将允许我找到给定的 menuItem(我已经有了),但没有与 MenuItem 关联的 ClientID
    • 谢谢约翰,我不知道。生成菜单时可以伪造 ID 吗?添加带有值的属性,还是通过继承 MenuItem 并自己添加 ID 来创建自定义 MenuItem 控件?
    • 到目前为止,我看到的唯一方法是使用“最佳猜测”方法,在该方法中获取 ParentID,计算添加元素的顺序,然后将数字附加到末尾,例如 ct0001_NavMenu_1 ct0001_NavMenu_2 等等
    • 数据绑定的时候,有没有试过把ID加到MenuItem的Value中?还是您将 value 字段用于其他内容并且无法更改?
    • 我们可以通过将 A 目标设置为一些奇怪的东西然后在 jQuery 中处理它来强制它工作,但显然这不是一个修复,只是一个 hack。很想知道是否有“真正的”解决方法。
    【解决方案5】:

    Asp:menu 提供一组 CSS 属性,例如hoverCss/SelectCss .

    如果您选择(鼠标悬停/单击)一个菜单项,cssclass 是否会添加到 html 控件(a)上?

    如果答案是“是”,则使用

    $('.thecssclassuspecified').live('click',function(){

                                    $(this)....
    
                                  });
    

    或者'不',恐怕你必须使用类似下面的代码,因为VS 2010之前的asp控件不适合js和jquery。

    $('menu > a').live('click', function(){

                           $(this)... 
    
                   });
    

    【讨论】:

      【解决方案6】:

      当绑定菜单(OnMenuItemDataBound)时,您可能可以添加带有一些 ID 的自定义属性,以便以后在 JavaScript 中使用。

      更新:MenuItem 没有Attributes 属性,所以它是死路一条。此外,由于 MenuItem 是密封的,因此没有更改的余地。但是菜单是公共课程,所以也许可以在那里完成。整个 Menu/MenuItem 对修改不友好,所以我认为您必须编写很多自定义代码。

      或者使用Adapters

      如果由我决定,我会放弃 asp.net 菜单并完全自定义。

      【讨论】:

      • MenuItem 直接从对象继承,即使它位于 System.Web.UI.WebControls 命名空间中,所以这就是为什么没有 Attributes 属性 msdn.microsoft.com/en-us/library/…
      • 我知道,我看过源码
      【解决方案7】:

      这些答案中的大多数都为定位某个链接并使用它做某事提供了很好的想法。问题是您不知道数据库将生成哪些链接,并且它们没有设置可供选择的客户端 ID。

      您可能不喜欢这个答案,但最终您需要实现一些可以让您识别链接的东西,无论它是class 还是id 属性最终都无关紧要。

      粗略的想法可能是:

      • 编号/命名约定客户端。例如,在页面准备就绪时,使用 jQuery 来解析锚点,可能是它们的类或 href 值,并使用这些数据以常规方式设置客户端 ID。

      • 更改数据库架构以允许将客户端 ID 与链接详细信息一起存储。这可能需要最多的工作,因为这意味着更改架构、对象和方法等...但它应该不会太难,并且可能是您最安全、最干净的解决方案。

      我确定还有其他选择,但关键是您需要以某种方式识别您的链接,然后脚本才能为您提供帮助。

      【讨论】:

        猜你喜欢
        • 2020-11-04
        • 1970-01-01
        • 1970-01-01
        • 2017-11-16
        • 1970-01-01
        • 1970-01-01
        • 2018-04-25
        • 1970-01-01
        • 2013-01-24
        相关资源
        最近更新 更多