24

I'm in the process of styling an asp.net menu and I'm trying to understand the meaning of the StaticSelectedStyle-CssClass and StaticHoverStyle-CssClass parameters.

My understanding is that the styles defined with these parameters are applied as CSS classes to the relevant elements, whenever needed. So I created my menu as follows:

<asp:Menu ID="NavigationMenu" DataSourceID="NavigationSiteMapDataSource" 
        StaticMenuStyle-CssClass="StaticMenuStyle"
        StaticMenuItemStyle-CssClass="StaticMenuItemStyle"
        StaticSelectedStyle-CssClass="StaticSelectedStyle"
        StaticHoverStyle-CssClass="StaticHoverStyle"
        Orientation="Horizontal" 
        MaximumDynamicDisplayLevels="0" 
        runat="server">
</asp:Menu>

It works for StaticMenuStyle-CssClass and StaticMenuStyle-CssClass (the classes are applied to the relevant elements), but StaticSelectedStyle-CssClass and StaticHoverStyle-CssClass are not applied, regardless of the selected or hover status of an element.

What am I supposed to do to make this work?

Thanks.

EDIT: Sorry I should have mentioned that this is .NET 4. Here is the generated HTML:

<div id="NavigationMenu">
 <ul class="level1 StaticMenuStyle">
  <li><a class="level1 StaticMenuItemStyle selected" href="/Link.aspx">Link</a></li>
 </ul>
</div>

So as you can see, StaticMenuStyle and StaticMenuItemStyle are applied, but not StaticSelectedStyle-CssClass or StaticHoverStyle-CssClass. Not sure why. I know I can use selected but isn't the expected behavior that StaticSelectedStyle-CssClass be applied??? By using selected I make assumptions as to what .NET does behind the scenes and that's not right.

Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
md1337
  • 1,440
  • 2
  • 16
  • 32
  • It works fine for me (with a simpler example - my menu isn't databound, for example). Could you post the relevant CSS classes, and perhaps some rendered HTML? – Jeff Sternal Apr 16 '10 at 19:02
  • Look in the markup for some Javascript that sets the hover style. In the original layout with tables the selected style was only applied after you clicked on one of the menu options and the menu did a postback. – Harv Apr 16 '10 at 21:43
  • 4
    Nope, didn't help. My classes are not being set no matter what. Looks like a bug. – md1337 Apr 17 '10 at 01:09

11 Answers11

35

I feel your pain and I wasted all night/morning trying to figure this out. With sheer brute force I figured out a solution. Call it a workaround - but it's simple.

Add the CssClass property to your Menu Control's declaration like so:

<asp:Menu ID="NavigationMenu" DataSourceID="NavigationSiteMapDataSource"
        CssClass="SomeMenuClass"
        StaticMenuStyle-CssClass="StaticMenuStyle"
        StaticMenuItemStyle-CssClass="StaticMenuItemStyle"
        Orientation="Horizontal" 
        MaximumDynamicDisplayLevels="0" 
        runat="server">
</asp:Menu>

Just rip out the StaticSelectedStyle-CssClass and StaticHoverStyle-CssClass attributes as they simply don't do jack.

Now create the "SomeMenuClass", doesn't matter what you put in it. It should look something like this:

.SomeMenuClass
{
    color:Green;
}

Next add the following two CSS Classes:

For "Hover" Styling add:

.SomeMenuClass a.static.highlighted
{
    color:Red !important;
}

For "Selected" Styling add:

.SomeMenuClass a.static.selected
{
    color:Blue !important;
}

There, that's it. You're done. Hope this saves some of you the frustration I went through. BTW: You mentioned:

I seem to be the first one to ever report on what seems to be a bug.

You also seemed to think it was a new .NET 4.0 bug. I found this: http://www.velocityreviews.com/forums/t649530-problem-with-staticselectedstyle-and-statichoverstyle.html posted back in 2008 regarding Asp.Net 2.0 . How are we the only 3 people on the planet complaining about this?

How I found the workaround (study the HTML output):

Here is the HTML output when I set StaticHoverStyle-BackColor="Red":

#NavigationMenu a.static.highlighted
{
    background-color:Red;
}

This is the HTML output when setting StaticSelectedStyle-BackColor="Blue":

#NavigationMenu a.static.selected
{
    background-color:Blue;
    text-decoration:none;
}

Therefore, the logical way to override this markup was to create classes for SomeMenuClass a.static.highlighted and SomeMenuClass a.static.selected

Special Notes:

You MUST also use "!important" on ALL the settings in these classes because the HTML output uses "#NavigationMenu", and that means any styles Asp.Net decides to throw in there for you will have inheritance priority over any other styles for the Menu Control with the ID "NavigationMenu". One thing I struggled with was padding, till I figured out Asp.Net was using "#NavigationMenu" to set the left and right padding to 15em. I tacked on "!important" to my SomeMenuClass styles and it worked.

MikeTeeVee
  • 18,543
  • 7
  • 76
  • 70
  • 2
    Whew! I tried this, and you're right. I think nobody uses the ASP.Net Menu because it's so hosed. They keep enhancing it in every release, but they just don't seem to understand the basic requirements. How could you NOT want to indicate the selected item on a menu??? – DOK Aug 08 '11 at 18:16
  • 1
    I think most people give up and just build their own menu from scratch. I hung in there and was eventually able to make it work, but I had to study the generated html to figure out how to write CSS for it and then repeatedly tweak it until it rendered the same in all browsers for the past 3 versions. What a pain, but I was able to avoid building a custom interactive menu using javascript. One thing to note is the ASP.net menu's default Rendering Mode changed in 4.0 . See the "Remarks" section here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.menu.renderingmode.aspx – MikeTeeVee Aug 08 '11 at 21:35
  • @MikeTeeVee This just saved me hours, thanks. Any chance you know how to add a separator image in between each horizontal menu link? – Mark B Oct 03 '11 at 18:15
8

Alright, so there are obviously not a whole lot of people who have tried the .NET 4 menu as of today. Not surprising as the final version was released a couple days ago. I seem to be the first one to ever report on what seems to be a bug. I will report this to MS if I find the time, but given MS track-record of not paying attention to bug reports I'm not rushing this.

Anyway, at this point the least worst solution is to copy and paste the CSS styles generated by the control (check the header) into your own stylesheet and modify it from there. After you're done doing this, don't forget to set IncludeStyleBlock="False" on your menu so as to prevent the automatic generation of the CSS, since we'll be using the copied block from now on. Conceptually this is not correct as your application shouldn't rely on automatically generated code, but that's the only option I can think of.

md1337
  • 1,440
  • 2
  • 16
  • 32
  • I just named my selected class "selected" and it worked ok for me, thanks for the hint – MikeAinOz Dec 08 '10 at 07:24
  • Your solution seems best to me since I don't need to override styling for implementation-specific classes like 'a.static'. I did lose a few styles I needed, but I'm now able to style based on ONLY the classes I specify in the CssClass attributes for the menu and items. – madannes Sep 23 '16 at 20:52
4

I remember the StaticSelectedStyle-CssClass attribute used to work in ASP.NET 2.0. And in .NET 4.0 if you change the Menu control's RenderingMode attribute "Table" (thus making it render the menu as s and sub-s like it did back '05) it will at least write your specified StaticSelectedStyle-CssClass into the proper html element.

That may be enough for you page to work like you want. However my work-around for the selected menu item in ASP 4.0 (when leaving RenderingMode to its default), is to mimic the control's generated "selected" CSS class but give mine the "!important" CSS declaration so my styles take precedence where needed.

For instance by default the Menu control renders an "li" element and child "a" for each menu item and the selected menu item's "a" element will contain class="selected" (among other control generated CSS class names including "static" if its a static menu item), therefore I add my own selector to the page (or in a separate stylesheet file) for "static" and "selected" "a" tags like so:

a.selected.static
{
background-color: #f5f5f5 !important;
border-top: Red 1px solid !important;
border-left: Red 1px solid !important;
border-right: Red 1px solid !important;
} 
3

I ran into the issue where the class of 'selected' wasn't being added to my menu item. Turns out that you can't have a NavigateUrl on it for whatever reason.

Once I removed the NavigateUrl it applied the 'selected' css class to the a tag and I was able to apply the background style with:

div.menu ul li a.static.selected
{
    background-color: #bfcbd6 !important;
    color: #465c71 !important;
    text-decoration: none !important;
}
ryanjones
  • 5,383
  • 4
  • 28
  • 24
2

I tried MikeTeeVee's solution, still not work, I mean the selected tab still not change and keep different color. This post solved my problem: Set CSS class 'selected' in ASP.NET menu parents and their children? Need put code in code behind.

Community
  • 1
  • 1
Charles
  • 161
  • 1
  • 3
  • 12
  • This worked for me - my situation was slightly different to OP in that my menu was statically defined rather than using a datasource. – Gary Stacey Feb 08 '16 at 08:45
2

Just want to throw something in to help people still having this problem. (for me at least) the css is showing that it puts default classes of level1, level2, and level3 on each piece of the menu(level 1 being the menu, level2 being the first dropdown, level3 being the third popout). Setting the padding in css

.level2
{
padding: 2px 2px 2px 2px;
}

does work for adding the padding to each li in the first dropdown.

DaveShaw
  • 52,123
  • 16
  • 112
  • 141
jeremy
  • 21
  • 1
1

The thing to look at is what HTML is being spit out by the control. In this case it puts out a table to create the menu. The hover style is set on the TD and once you select a menu item the control posts back and adds the selected style to the A tag of the link within the TD.

So you have two different items that are being manipulated here. One is a TD element and another is an A element. So, you have to make your CSS work accordingly. If I add the below CSS to a page with the menu then I get the expected behavior of the background color changing in either case. You may be doing some different CSS manipulation that may or may not apply to those elements.

<style>
    .StaticHoverStyle
    {
        background: #000000;
    }

    .StaticSelectedStyle
    {
        background: blue;
    }
</style>
Harv
  • 555
  • 6
  • 17
  • 2
    I appreciate the comment. I failed to mention this is .NET 4 so the default rendering is a list, not a table. – md1337 Apr 16 '10 at 20:40
  • 1
    Then I would check what styles are being applied to the list. I don't have VS2010 installed here so I can't really give you any direct tips, but if it works in similar fashion to the original setup then they are applying some sort of styles either directly to the resulting markup or using javascript and you need to check what those are and where they are being applied. – Harv Apr 16 '10 at 20:56
  • 3
    You are right and I had noticed that, but see my edit for the reason why I think this is not the solution. – md1337 Apr 16 '10 at 21:17
1

I don't know why all the answers over here are so confusing. I found a quite simpler one. Use a css class for the asp:menu, say, mainMenu and all the menu items under this will be "a tags" when rendered into HTML. So you just have to provide :hover property to those "a tags" in your CSS. See below for the example:

<asp:Menu ID="mnuMain" Orientation="Horizontal" runat="server" Font-Bold="True" Width="100%" CssClass="mainMenu">
  <Items>
    <asp:MenuItem Text="Home"></asp:MenuItem>
    <asp:MenuItem Text="About Us"></asp:MenuItem>
  </Items>
</asp:Menu>

And in the CSS, write:

.mainMenu { background:#900; }
.mainMenu a { color:#fff; }
.mainMenu a:hover { background:#c00; color:#ff9; }

I hope this helps. :)

Sonam
  • 11
  • 2
0

You can try styling with LevelSubMenuStyles

            <asp:Menu ID="mainMenu" runat="server" Orientation="Horizontal" 
                StaticEnableDefaultPopOutImage="False">
                <StaticMenuStyle CssClass="test" />
                <LevelSubMenuStyles>
                    <asp:SubMenuStyle BackColor="#33CCFF" BorderColor="#FF9999" 
                        Font-Underline="False" />
                    <asp:SubMenuStyle BackColor="#FF99FF" Font-Underline="False" />
                </LevelSubMenuStyles>
                <StaticMenuItemStyle CssClass="main-nav-item" />
            </asp:Menu>
Prasanna
  • 4,583
  • 2
  • 22
  • 29
0

The best results I had with this broken control involved not using css at all, but rather using the built-in control properties for style (DynamicMenuItemStyle-BackColor, StaticHoverStyle-Width, etc.). This is terrible practice and bloats your code, as well as forcing you to do this for every instance of the control.

This does however work.

ScottLenart
  • 1,160
  • 1
  • 12
  • 15
-1

There are well achieved third-party tools, but i usually use superfish http://www.conceptdevelopment.net/Fun/Superfish/ it's cool, free and easy ;)

a52
  • 366
  • 3
  • 8