可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a item on a page, which has a series of MenuItems (generated dynamically from a database) as Items of the Menu.
Each MenuItem renders itself as
<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">
However I would like to get the ClientID of this link (we use a external Javascript library to popup pages in modal lightbox style frames). One of the requirements of this is that we need to identify the "clickable object ID" so we can set it up to be able to fire the event on click.
Everywhere else on our site we have
OurSite.SetupDialogueBoxForOpen('<%= HyperLink.ClientID =>');
However for some reason the menu item does not appear to have a ClientID property assigned to it. Which makes setting the client id in JavaScript near impossible.
Does anyone know how to get a ClientID of a menuitem (just for clarification the menu item is of type System.Web.UI.WebControls.MenuItem
Thanks in advance!
回答1:
If you want to change the way items in the control are rendered, you can use the StaticMenuItemTemplate
and DynamicMenuItemTemplate
properties. I will only use the first in my example (static, for top-level items):
<asp:Menu runat="server" ...>
<StaticMenuItemTemplate>
<a id="<%# GetSuitableClientId(Container) %>"><%# Eval("Text") %></a>
</StaticMenuItemTemplate>
</asp:Menu>
The StaticMenuItemTemplate
property is of type ITemplate
and as is often the case with such template properties it is decorated with the TemplateContainer
attribute. This specifies the container in which the template is to be instantiated, usually the container gives access to some context that you may need in rendering. In this case it is of type MenuItemTemplateContainer
which implements IDataContainer
and thus gives access to the data item.
So we pass this container back to a method in our page, and in that method we construct an ID as we see fit. We could use the data item for depth, and the container for the index for instance:
protected string GetSuitableClientId(MenuItemTemplateContainer container)
{
MenuItem item = (MenuItem)container.DataItem;
return String.Format("menuItem-{0}-{1}", item.Depth, container.ItemIndex);
}
My guess in constructing this answer is that you can now adjust your JavaScript to bind to click events on the <a id="menuItem-2-4">Text</a>
element since you now have predictable client-side IDs.
Edit: you can also use the following inside your template and let the ASP.NET take care of creating the unique client-side ID, but that is less predictable...
<asp:HyperLink ID="MenuItem" runat="server" NavigateUrl='<%# Eval("NavigateUrl") %>' />
回答2:
What about getting a list of every anchor tag in the DOM and iterating through them looking at .class until you find the class=="whatever_Nav_ID_or_flag_you_entered_or_somehow_can_tell_this_element_apart" and then using .id to assign an id to it? Something like: untested
var anchors = document.getElementsByTagName("a");
for(int i = 0; i < anchors.length()){
if(anchors[i].class=="testClass"){
anchors[i].id = "targetThisAnchor";
break;
}
}
EDIT:
during render you could use a conditional to see if the new menuitem is the one you are looking for?
<%
if (MenuItem.flag == menuItemToTarget)
{
//set MenuItem id
}
%>
回答3:
Try this, change the selector $("menu > a").bind('click',function(){}));
回答4:
You would get to the menu item like this:
OurSite.SetupDialogueBoxForOpen('<%= uxHeaderMenu.FindControl("menuPageNav_3").ClientID %>');
Since you didn't post any code, I can't tell you how to specifically pick the third one (in the above case).... but this should work.
You need to use FindControl because the MenuItem is a child of Menu, not a child of the Page, or User Control.
回答5:
Asp:menu provide a set of CSS properties, e.g. hoverCss/SelectCss .
if you select (mouseOver/click) one menu item, will the cssclass add on the html control(a)?
if the answer is 'Yes' , then use
$('.thecssclassuspecified').live('click',function(){
$(this)....
});
or 'No', i'm afraid you have to use something like the code below, caz asp controls before VS 2010 are not perfect for js and jquery.
$('menu > a').live('click', function(){
$(this)...
});
回答6:
When binding the menu (OnMenuItemDataBound) you can probably add custom attribute with some ID which can be later used in JavaScript.
Update: MenuItem does not have Attributes property, so it is dead end. Also, since MenuItem is sealed there is no room for change. But Menu is public class, so maybe it can be done there. This whole Menu/MenuItem is not modification-friendly, so i think that you must write a lot of custom code.
Or use Adapters for it.
If it was up to me i would drop asp.net menu and wrote it completely custom.
回答7:
Most of these answers provide great idea for targeting a certain link and doing something with it. The issue is that you do not know what links will be produced by the database and they do not have a client ID set to select from.
You may not like the answer but ultimately you need to implement something that will allow you to identify the links whether it is a class
or id
property ultimately is irrelevant.
Roughly thought ideas might be:
Numbering/naming convention client-side. For example, on page ready use jQuery to parse the anchors, maybe their class or href values and use this data to set the client Id conventionally.
Alter the DB schema to allow a client ID to be stored with the link details. This would require the most work likely because it means changing schema, objects, and methods, etc... but it shouldn't be too hard, and would likely be your safest, cleanest solution.
I'm sure there are other options, but the key is you need to identify your links somehow before script will help you at all.