Set CSS class 'selected' in ASP.NET menu parents and their children? - asp.net

I have the following menu control embedded in the Site.master file:
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal" RenderingMode="List">
<Items>
<asp:MenuItem NavigateUrl="~/Default.aspx" Text="Home" />
<asp:MenuItem NavigateUrl="~/TechServices.aspx" Text="Tech Services"/>
<asp:MenuItem NavigateUrl="~/HumanResources.aspx" Text="Human Resources"/>
<asp:MenuItem NavigateUrl="~/Marketing.aspx" Text="Marketing"/>
<asp:MenuItem NavigateUrl="~/DocumentControl.aspx" Text="Document Control"/>
<asp:MenuItem NavigateUrl="~/IT.aspx" Text="Information Tech"/>
</Items>
</asp:Menu>
In order to set the CSS class attribute selected I use the following C# code:
protected void Page_Load(object sender, EventArgs e) {
string thispage = this.Page.AppRelativeVirtualPath;
int slashpos = thispage.LastIndexOf('/');
string pagename = thispage.Substring(slashpos + 1);
foreach (MenuItem mi in NavigationMenu.Items) {
if (mi.NavigateUrl.Contains(pagename)) {
mi.Selected = true;
break;
}
}
}
The code above works great. However, these pages now contain sub-pages (children) and I would like to parent pages retain their "Selected" CSS attribute when accessing one of their children pages.
I also created the Web.sitemap file to organize all the parent and their children pages. However, I am stock on how to use the Web.sitemap to help the C# function above to help the parent menu retain their CSS class "selected" attribute. I am not sure if I need the Web.sitemap file for this purpose? The parent and child logic is only available in the Web.sitemap file.

Once you find the MenuItem to select just traverse upward and select all parent. Here's some pseudo-code:
MenuItem miP = mi.Parent;
while (miP != null)
{
miP.Selected = true;
if (miP.Parent == null)
break;
else
miP = miP.Parent;
}

Related

Passing a value from menu items

I would like to pass a value from menu item to the respected navigation page.
<asp:menu id="myMenu"
staticdisplaylevels="2"
staticsubmenuindent="10"
orientation="Horizontal"
dynamichorizontaloffset="10"
onmenuitemclick="myMenu_MenuItemClick"
target="_blank"
runat="server" ForeColor="White" >
<items>
<asp:menuitem
text="Home"
tooltip="Home">
<asp:menuitem
text="Music"
tooltip="Music">
<asp:menuitem
text="Classical"
tooltip="Classical"/>
<asp:menuitem
text="Rock"
tooltip="Rock"/>
<asp:menuitem
text="Jazz"
tooltip="Jazz"/>
</asp:menuitem>
<asp:menuitem
text="Movies"
tooltip="Movies">
<asp:menuitem
text="Action"
tooltip="Action"/>
<asp:menuitem
text="Drama"
tooltip="Drama"/>
<asp:menuitem
text="Musical"
tooltip="Musical"/>
</asp:menuitem>
</asp:menuitem>
</items>
</asp:menu>
The code to pass the MenuItem Text is as below:
protected void myMenu_MenuItemClick(object sender, EventArgs e)
{
Session["1"] = (sender as MenuItem).Text;
Response.Redirect("~/CategorySearch.aspx?Category=" + Session["1"].ToString());
}
I get a NullReferenceException which is quite interesting because I am just passing the text of the MenuItem.Why is that?
If you have an event handler attached to your menu (or menu item), you can easily cast the sender as a MenuItem like so:
Webforms:
<asp:Menu runat="server" ID="mymenu" OnMenuItemClick="mymenu_MenuItemClick">
<Items>
<asp:MenuItem Text="Home" />
<asp:MenuItem Text="Contact" />
<asp:MenuItem Text="About Us" />
</Items>
</asp:Menu>
Code Behind:
protected void mymenu_MenuItemClick(object sender, MenuEventArgs e)
{
// this is the menu itself, you can iterate the Items collection if you need.
var menu = (sender as Menu);
foreach (MenuItem item in menu.Items)
{
System.Diagnostics.Debug.Print(item.Text);
}
// this is the MenuItem object that was clicked
var clickedMenuItem = e.Item;
// store text value in your session
Session["1"] = e.Item.Text;
// redirect
Response.Redirect("~/CategorySearch.aspx?Category=" + e.Item.Text);
}

Ext.net:PreviousPage.FindControl issue

I have main page something like this.
<ext:ResourceManager ID="ResourceManager1" runat="server" Theme="Gray" />
<form id="form2" runat="server">
<ext:Panel runat="server" ID="anaPanel" Title="OSO" Icon="Car">
<TopBar>
<ext:Toolbar runat="server" Layout="FitLayout">
<Items>
<ext:Menu ID="Menu1" runat="server" Floating="false" Layout="HBoxLayout" ShowSeparator="false"
AnimCollapse="true" Cls="horizontal-menu">
<Defaults>
<ext:Parameter Name="MenuAlign" Value="tl-bl?" Mode="Value" />
</Defaults>
<Items>
<ext:MenuItem ID="MenuItem1" runat="server" Text="" Icon="Group">
<Menu>
<ext:Menu ID="Menu2" runat="server">
<Items>
<ext:MenuItem Text="new card" Icon="GroupAdd">
<DirectEvents>
<Click OnEvent="AddNewCart_Click"></Click>
</DirectEvents>
</ext:MenuItem>
...............
...............
</ext:Panel>
<ext:Window runat="server" ID="MyWindow" Hidden="true"></ext:Window>
</form>
My maninpage codebehind something like this.
protected void AddNewCart_Click(object sender, DirectEventArgs e)
{
string path = "Pages/Kart.aspx";
Window win = CreateWindows(MyWindow,Icon.Group,path,"new card", 420, 500);
//private Window CreateWindows(Window Mywindow , Icon ic,string path,string Title, int Heigh, int With){......};
//I get the MyWindow and pass some values and turn it back.
win.Render(this.Form);
win.Show();
}
inside the Kart.aspx I have some buttons,my first question is ,how can I close this window .I put a button to close the this window(window which loaded Kart.aspx) ,here are the some way how I did.but none of them didnt work.
1-
if (PreviousPage != null)//previouspage come as a null.
{
Window wnd = PreviousPage.FindControl("MyWindow") as Window;
wnd.Close();
}
2-
Window wnd = Parent.Page.FindControl("MyWindow") as Window;
wnd.Close();
3-I also tried to make MyWindow as public inside mainpage and try to reach it from Kart.aspx,but also didnt work
my second question is ,how can I pass the parameters between the those pages.
you can do it in the client side by calling
window.parent.Ext.getCmp('MyWindow').close();
Edit
the closest to a code behind call is to use
btnClose.AddScript("window.parent.Ext.getCmp('MyWindow').close();");
Edit 2
if you code is more complex like reloading a grid or modifying forms, you do the following:
Code-Behind
X.Call("ReloadGrid");
JavaScript
function ReloadGrid() {
var grid = window.parent.Ext.getCmp('GridId');
//grid reloading code
}

Displaying a context menu for Column Headers of an AspxGridView

I read about the popup menu in the documentation here. I'm not clear as to whether this menu is already provided and we just have to enable a particular property to make it available? Or is it just an example of a popup menu and needs to be created? I've just begun exploring devexpress grids and any help would be appreciated.
This topic is devoted to the XtraGrid - the Winforms Grid. The ASPxGridView does not provide this menu, you may try to implement it yourself as it is shown in the
ASPxGridView - How to implement showing/hiding columns in the manner similar to ASPxPivotGrid
example.
It is possible we can create context menu on aspxgridview. Find the following example for aspxgridview context menu.
Default.aspx:
=============
<dx:ASPxGridView ID="grvContexMenuExample" runat="server" AutoGenerateColumns="false"
KeyFieldName="ID" EnableViewState="true" ClientInstanceName="grdtest" Width="100%"
Settings-GridLines="None" OnHtmlRowPrepared="grvContexMenuExample_HtmlRowPrepared">
<ClientSideEvents ContextMenu="function(s,e) {
if(e.objectType == 'header')
{
headerContextMenu.ShowAtPos(e.htmlEvent.clientX, e.htmlEvent.clientY);
}
else if(e.objectType == 'row')
{
headerContextMenu.ShowAtPos(e.htmlEvent.clientX, e.htmlEvent.clientY);
}
}" />
<Columns>
<%--Your columns goes here--%>
<columns>
</dx:ASPxGridView>
<!--Start New Context Menu !-->
<dx:ASPxPopupMenu ID="mnContextMenu" runat="server" ClientInstanceName="headerContextMenu"
EnableAnimation="false" PopupHorizontalAlign="OutsideRight" PopupVerticalAlign="TopSides"
PopupAction="RightMouseClick">
<Items>
<dx:MenuItem Text="New Context Menu1">
</dx:MenuItem>
</Items>
<ClientSideEvents ItemClick="ContextMenuItemClick" />
</dx:ASPxPopupMenu>
<!--End New Context Menu !-->
Default.aspx.cs:
================
protected void grvContexMenuExample_HtmlRowPrepared(object sender, ASPxGridViewTableRowEventArgs e)
{
if (e.RowType == GridViewRowType.Data)
if (e.RowType == GridViewRowType.Header)
{
e.Row.Attributes.Remove("oncontextmenu");
}
}

ASP.NET: Highlight menu item of current page

I've been trying to find an easy way of highlighting the current selected menu item of an asp.net menu (so the user knows which page they are on), but no matter what I have tried I can't get it to work. In my markup I have:
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal" StaticSelectedStyle-ForeColor="#99CCFF" DynamicSelectedStyle-ForeColor="#99CCFF">
<Items>
<asp:MenuItem NavigateUrl="~/Default.aspx" Text="Operations"/>
<asp:MenuItem NavigateUrl="~/Analysis.aspx" Text="Analysis"/>
<asp:MenuItem NavigateUrl="~/Dashboard.aspx" Text="Dashboard"/>
<asp:MenuItem NavigateUrl="~/Flashboard.aspx" Text="Flashboard"/>
<asp:MenuItem NavigateUrl="~/Spacequest.aspx" Text="SQ OBP"/>
</Items>
</asp:Menu>
And in the server side Page_Load function:
((Menu)Master.FindControl("NavigationMenu")).Items[0].Selected = true;
But this does not work. I tried using a sitemap (even though a sitemap is not what I want to use) and that hasn't worked either. Any ideas?
There's a StaticSelectedStyle property that you can use inside your menu.
<asp:menu [...]>
<staticselectedstyle backcolor="LightBlue"
borderstyle="Solid"
bordercolor="Black"
borderwidth="1"/>
[...]
</asp:menu>
See here for more info.
Also, if there's a class applied to the selected item (which i'm not sure if there is but it would be handy) you can simply hook into that with your CSS. This would be a much nicer way than using the StaticSelectedStyle property.
UPDATE
It's worth noting also that your use of IncludeStyleBlock="false" will stop your menu from generating the CSS necessary to control the selected item.
With the style block turned off, you have to provide your own styles and the auto-generated styles of the menu will not be used.
From MSDN:
If you set this property to false, you cannot set style properties.
For example, you cannot add a DynamicHoverStyle-ForeColor attribute in
markup or set the DynamicHoverStyle.ForeColor property in code.
Source: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.menu.includestyleblock.aspx
I think you'll have to loop through the menu items and see if the current page URL contains the NavigateUrl of the menu item.
foreach (MenuItem item in mn.Items)
{
if (Request.Url.AbsoluteUri.ToLower().Contains(Page.ResolveUrl(item.NavigateUrl.ToLower()))
{
item.Selected = true;
}
}
I would use jQuery in this instance.
For the specified page, so for example on the Analysis.aspx page, add this bit of jquery to your page.
$('#MenuItemID').addClass('active');
Can you specify the ID of the menu items?
Such as:
<asp:MenuItem ID="AnalysisMenuItem" NavigateUrl="~/Analysis.aspx" Text="Analysis"/>
You would then use this:
$('#' + <% AnalysisMenuItem.ClientID %>').addClass('active');
then of course just define what active is in your css:
.active { background-color: #FFF; }
If you are thinking to make it dynamically, then this is the better way:
Menu MyMenu = new Menu();
....
MyMenu.MenuItemDataBound += new MenuEventHandler(MyMenu_MenuItemDataBound);
TheMenu.StaticSelectedStyle.CssClass ="MySelectedClass";
protected void MyMenu_MenuItemDataBound(Object sender, MenuEventArgs e)
{
if (e.Item.NavigateUrl.ToLower().Contains(Path.GetFileName(Request.FilePath).ToLower()))
{
//e.Item.Text = "<div style='color: Yellow'>" + e.Item.Text + " </div>";
e.Item.Selected = true;
}
}
add then simply add .MySelectedClass style to your Css file
..
//Master
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu"
EnableViewState="False" Orientation="Horizontal"
BackColor="#465C71" DynamicHorizontalOffset="2"
ForeColor="#DDE4EC">
<StaticMenuItemStyle HorizontalPadding="15px" VerticalPadding="2px" />
<StaticSelectedStyle BackColor="#FFFFFF" ForeColor="#000000"/>
<Items>
<asp:MenuItem NavigateUrl="~/Secure/About.aspx" Text="About"/>
<asp:MenuItem NavigateUrl="~/Secure/Login.aspx" Text="Login"/>
</Items>
</asp:Menu>
//Master.cs
foreach (MenuItem item in ((Menu)this.FindControl("NavigationMenu")).Items)
{
if(Request.Url.AbsoluteUri.ToLower().Contains(item.NavigateUrl.ToLower().Substring(1)))
{
item.Selected = true;
}
}
//item.NavigateUrl.ToLower() contains "~". So, find substring and check.

ASP.Net Master Page Sidebar display after Login (keeping it displayed whilst logged in)

I have the following sidebar on my master page. It is not a part of any ContentPlaceHolder.
<div runat="server" visible="false" id="menuAccountMembersDiv" class="leftCol">
<asp:Menu ID="menuAccountMembers" runat="server" StaticSubMenuIndent="16px" Visible="false">
<Items>
<asp:MenuItem ImageUrl="~/Resources/x.png"
NavigateUrl="~/About.aspx" Text="x" ToolTip="x"
Value="b647ce4e-5c7f-400c-a921-ec7902494f26"></asp:MenuItem>
<asp:MenuItem ImageUrl="~/Resources/y.png"
NavigateUrl="~/About.aspx" Text="y" ToolTip="y"
Value="y"></asp:MenuItem>
<asp:MenuItem ImageUrl="~/Resources/sarahhunkin.png" NavigateUrl="~/About.aspx"
PopOutImageUrl="~/Resources/z.png" Text="z"
ToolTip="z" Value="z"></asp:MenuItem>
<asp:MenuItem ImageUrl="~/Resources/a.png"
NavigateUrl="~/About.aspx"
PopOutImageUrl="~/Resources/apop.png" Text="a"
ToolTip="a" Value="a"></asp:MenuItem>
</Items>
</asp:Menu>
</div>
I initially hide it. But I would like to display it and keep it displayed after logging in. Using the standard web application login page. I tried the following:
protected void LoginUser_LoggedIn(object sender, EventArgs e)
{
Menu MenuAccountMembers = (Menu)Master.FindControl("menuAccountMembers");
MenuAccountMembers.Visible = true;
Control menuAccountMembersDiv = (Control)Master.FindControl("menuAccountMembersDiv");
menuAccountMembersDiv.Visible = true;
}
I am not sure to to interact with the div tag, as there is no Div object. In any event, this does not display the sidebar with the menu
EDIT:
I ended up adding the following code to the master page itself.
public partial class SiteMaster : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
if (HttpContext.Current.Request.IsAuthenticated)
{
Control MenuDiv = this.FindControl("menuAccountMembersDiv");
MenuDiv.Visible = true;
Menu AccountMenu = (Menu)MenuDiv.FindControl("menuAccountMembers");
AccountMenu.Visible = true;
}
}
}
I would go for setting the visibiliy directly on your div based on authentication status
<div runat="server" visible="<%# Page.User.IsAuthenticated %>" id="menuAccountMembersDiv" class="leftCol">
that way you don't need your LoginUser_LoggedIn method and the menu will show/hide on every load depending on the user is logged in or not
And remember to remove the Visible="false" from your <asp:Menu> control, if the outer div is hidden, nothing inside it will be shown anyway.
Since you have the runat="server" tag in the menu's Div tag, you can reference it directly in code...
menuAccountMembersDiv.Style.Item("Display") = "none";
or
menuAccountMembersDiv.Visible = False;
A div tag is a HtmlGenericControl class. To get access to this class import namespace System.Web.UI.HtmlControls; and use something like this:
HtmlGenericControl div = Master.FindControl("menuAccountMembersDiv") as HtmlGenericControl;
if(div != null)
{
div.Visible = true;
}
Or you can move your menu to UserControl and hide or show just use ID of your UserControl.
Hope it will help you with your question.

Resources