MasterPages - Dynamically Created Menus Disappearing

G

Guest

I am playing around with creating some menus
dynamically, and they
create fine and show up ok when I want them to; but
when I select a
menu NavigateUrl at run time, the applicable url shows
up as
anticipated in the content place holder but the menu
disappears...

the menu is part of the master page and is not in the
content place holder...

anybody have any ideas?

am I missing something obvious?

when I create the same menu at design time it does not
exhibit this behavior...

thanks in advance.
 
M

Mark Rae

the menu is part of the master page and is not in the
content place holder...

That's good, but where is the code which does the dynamic generation of the
MenuItems collection...?
 
G

Guest

This is how I am binding, with the exception that I am calling
CreateMenuItemBinding from within the click event of a button for test
purposes...

http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.menuitembindingcollection.aspx

As I said everything works fine, all menu items show up as anticipated, then
when I select a menu item which loads the applicable NavigateUrl into the
MasterPage ContentPlaceHolder I lose the menu, it disappears, although the
NavagateUrl *.aspx appears in the ContentPlaceHolder as it should...

If I can get the menu to stick around after I select the NavigateUrl from
the menu I created dynamically and display the NavigateUrl in the MasterPage
ContentPlaceHolder, then I can move forward with my idea that I am kicking
around...

Thanks in advance.
 
M

Mark Rae

when I select a menu item which loads the applicable NavigateUrl into the
MasterPage ContentPlaceHolder

I'm not sure what you're doing here...

Generally speaking, in the MasterPage / ContentPage architecture, you do not
dynamically select the ContentPage through a menu - instead, you simply
navigate to another ContentPage which, when it loads, picks up its
MasterPage and merges the two files into one HTML document...

E.g. if you have Page1.aspx and Page2.aspx, both of which are ContentPages
and use the same MasterPage, your MenuItem should simply navigate to
Page2.aspx through its NavigateUrl property - it should certainly not be
trying to play about with the contents of the ContentPlaceHolder on the
MasterPage...
 
G

Guest

I hope this explains it better...

The master page that I am dynamically creating a menu on works fine...

I am trying to select the content page that I want to display on the same
master page; from the dynamic menu I created, much as you would do from a
TreeView control as is done on the MSDN page, it works as anticipated if I
create a static menu at design time; but using the same settings at runtime,
when I select a menu item it does display the content page as it is supposed
to but the menu disappears, even though it is part of the master page...
I want the menu to stick around in case I want to load a different content
page instead in the same MasterPage…

Thanks in advance.
 
M

Mark Rae

I hope this explains it better...

I'm afraid it doesn't...
I want the menu to stick around in case I want to load a different content
page instead in the same MasterPage.

Still seems to me that you're doing this backwards...

Menus don't really work the same way as TreeViews...

To change the ContentPage, you simply navigate to the other ContentPage - it
will automatically pick up its MasterPage and redraw the menu for you...
 
G

Guest

I am navigating to the applicable content page, using the NavigateUrl that is
selected via the menu, when I do the menu disapears...
 
E

Edwin Knoppert

Dump a button on the masterpage and click on it..
Will the menu dissapear as well?
This is usually due not rebuilding the menu again on page load.

sorry if i'm way off here.
 
G

Guest

thats how I am testing it, when I click on the button on the master page, I
dynamically build a menu, and it looks and works like I want it to at that
point...
then when I select a menu item which is wired to NavigateUrl to display the
applicable content page in the same master page's content place holder, it
shows the content page but the menu disappears...

thanks in advance.
 
M

Mark Rae

I am navigating to the applicable content page, using the NavigateUrl that
is
selected via the menu, when I do the menu disapears...

Ah well alright then - but that isn't, in fact what you actually said... You
said "...then when I select a menu item which loads the applicable
NavigateUrl into the MasterPage ContentPlaceHolder...", which is what I
thought you meant!

That's fine - you appear to be doing it correctly - you just have a problem
with nomenclature. Selecting a menu item doesn't load the applicable
NavigateUrl into the MasterPage ContentPlaceHolder - it's precisely the
reverse. Selecting a menu item navigates to the ContentPage which loads its
MasterPage.

However, that's by the by...

Back to the original question - where is the code which does the dynamic
menu creation...?
 
G

Guest

Here is the code behind for the master page...
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class MsMasterMenu1 : System.Web.UI.MasterPage
{
public String ActiveMenu
{
get
{
object obj = ViewState["ActiveMenu"];
return (obj == null) ? String.Empty : (string)obj;
}
set
{
ViewState["ActiveMenu"] = value;
}
}

public String ActiveMenuContainer
{
get
{
object obj = ViewState["ActiveMenuContainer"];
return (obj == null) ? String.Empty : (string)obj;
}
set
{
ViewState["ActiveMenuContainer"] = value;
}
}

public String ActiveMenuDataFile
{
get
{
object obj = ViewState["ActiveMenuDataFile"];
return (obj == null) ? String.Empty : (string)obj;
}
set
{
ViewState["ActiveMenuDataFile"] = value;
}
}

public String ActiveMenuXPath
{
get
{
object obj = ViewState["ActiveMenuXPath"];
return (obj == null) ? String.Empty : (string)obj;
}
set
{
ViewState["ActiveMenuXPath"] = value;
}
}

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState.Add("ActiveMenu", "");
ViewState.Add("ActiveMenuContainer", "");
ViewState.Add("ActiveMenuDataFile", "");
ViewState.Add("ActiveMenuXPath", "");
}

if (this.ViewState["ActiveMenu"].ToString() != "")
{
this.CreateMenu(this.ViewState["ActiveMenu"].ToString(),
this.ViewState["ActiveMenuContainer"].ToString(),
this.ViewState["ActiveMenuDataFile"].ToString(),
this.ViewState["ActiveMenuXPath"].ToString());
}
}

public void CreateMenu(string pstrMenuName, string
pstrActiveMenuContainer, string pstrActiveMenuDataFile, string
pstrActiveMenuXPath)
{
Menu WebMenu = new Menu();
XmlDataSource xds = new XmlDataSource();
xds.DataFile = pstrActiveMenuDataFile;
xds.ID = pstrMenuName + "XmlDs";
xds.XPath = pstrActiveMenuXPath;
WebMenu.Orientation = Orientation.Horizontal;
WebMenu.DataSourceID = xds.ID;
WebMenu.BackColor =
System.Drawing.ColorTranslator.FromHtml("#B5C7DE");
WebMenu.ForeColor =
System.Drawing.ColorTranslator.FromHtml("#284E98");
WebMenu.StaticMenuItemStyle.HorizontalPadding =
System.Web.UI.WebControls.Unit.Pixel(5);
WebMenu.StaticMenuItemStyle.VerticalPadding =
System.Web.UI.WebControls.Unit.Pixel(2);
WebMenu.DynamicHoverStyle.BackColor =
System.Drawing.ColorTranslator.FromHtml("#284E98");
WebMenu.DynamicHoverStyle.ForeColor = System.Drawing.Color.White;
WebMenu.DynamicMenuStyle.BackColor =
System.Drawing.ColorTranslator.FromHtml("#B5C7DE");
WebMenu.StaticSelectedStyle.BackColor =
System.Drawing.ColorTranslator.FromHtml("#507CD1");
WebMenu.DynamicSelectedStyle.BackColor =
System.Drawing.ColorTranslator.FromHtml("#507CD1");
WebMenu.DynamicMenuItemStyle.HorizontalPadding =
System.Web.UI.WebControls.Unit.Pixel(5);
WebMenu.DynamicMenuItemStyle.VerticalPadding =
System.Web.UI.WebControls.Unit.Pixel(2);
WebMenu.StaticHoverStyle.BackColor =
System.Drawing.ColorTranslator.FromHtml("#284E98");
WebMenu.StaticHoverStyle.ForeColor = System.Drawing.Color.White;
WebMenu.StaticSubMenuIndent =
System.Web.UI.WebControls.Unit.Pixel(10);
WebMenu.DynamicHorizontalOffset = 10;

MenuItemBinding binding;
binding = SetItemBinding("Menu", 0, "Text", "");
WebMenu.DataBindings.Add(binding);
binding = SetItemBinding("Item", 1, "Text", "TargetUrl");
WebMenu.DataBindings.Add(binding);

Control ctrlMenuContainer =
this.frmMain.FindControl(pstrActiveMenuContainer);
ctrlMenuContainer.Controls.Add(xds);
ctrlMenuContainer.Controls.Add(WebMenu);
}

protected MenuItemBinding SetItemBinding(String pstrDataMember, Int32
pintDepth, String pstrTextField, String pstrTargetUrlField)
{
MenuItemBinding binding = new MenuItemBinding();

binding.DataMember = pstrDataMember;
binding.Depth = pintDepth;
binding.TextField = pstrTextField;
binding.NavigateUrlField = pstrTargetUrlField;

return binding;
}

protected void btnCreateMenu_Click(object sender, EventArgs e)
{
this.ActiveMenu = "TestMenu";
this.ActiveMenuContainer = "MasterMenuPanelA";
this.ActiveMenuDataFile = "~/Menu.xml";
this.ActiveMenuXPath = "/Root/Menu";

this.CreateMenu(this.ActiveMenu, this.ActiveMenuContainer,
this.ActiveMenuDataFile, this.ActiveMenuXPath);
}
}

here is the html from the master page...
<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="MsMasterMenu1.master.cs" Inherits="MsMasterMenu1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Test Master Menu Page</title>
</head>
<body>
<form id="frmMain" runat="server">
<div>
<table border="0" cellpadding="0" cellspacing="0" style="width: 100%;
height: 100%">
<tr>
<td colspan="2" style="height: 200px">
TODO: ...
</td>
</tr>
<tr>
<td style="width: 200px">
TODO: ... <br />
<asp:Button ID="btnCreateMenu" runat="server"
OnClick="btnCreateMenu_Click" Text="Create Menu" />
</td>
<td>
<asp:panel ID="MasterMenuPanelA" runat="server" Height="50px"
Width="125px" >
</asp:panel>
<asp:contentplaceholder id="MainContentPlaceHolder"
runat="server">
</asp:contentplaceholder>
</td>
</tr>
<tr>
<td colspan="2" style="height: 200px">
TODO: ...
</td>
</tr>
</table>

</div>
</form>
</body>
</html>

here is the default consumer page code behind...
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class ConsumeMsMasterMenu1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}

here is the html for the default consumer page...
<%@ Page Language="C#" MasterPageFile="~/MsMasterMenu1.master"
AutoEventWireup="true" CodeFile="ConsumeMsMasterMenu1.aspx.cs"
Inherits="ConsumeMsMasterMenu1" Title="Untitled Page" %>
<%@ MasterType VirtualPath="~/MsMasterMenu1.master" %>
<asp:Content ID="ContentDefault"
ContentPlaceHolderID="MainContentPlaceHolder" Runat="Server">
Default content page
</asp:Content>

here is the code behind for the select menu item content page...
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class SelectMenuItemContentPage1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}

here is the html for the select menu item content page...
<%@ Page Language="C#" MasterPageFile="~/MsMasterMenu1.master"
AutoEventWireup="true" CodeFile="SelectMenuItemContentPage1.aspx.cs"
Inherits="SelectMenuItemContentPage1" Title="Untitled Page" %>
<asp:Content ID="ContentMenuItem1"
ContentPlaceHolderID="MainContentPlaceHolder" Runat="Server">
Selected item from menu content page
</asp:Content>
 
M

Mark Rae

Wow! Seems incredibly over-complex to me, but no matter...
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)

Set a breakpoint on the above line, and run your site in Debug mode -
there's your problem...
 
G

Guest

I set a watch on the ActiveMenu and related properties as well as page load...

I am losing the values in ViewState as soon as I select the menu item
(setting NavigateUrlField) and "before" it gets back to page load where you
might think all values might be zeroed out...

don't see where I am losing viewstate...

thanks in advance.
 
B

BillE

I have a treeview in a master page which loads dynamically.

I have to rebuild the treeview on each postback, like Edwin said, or it will
be empty. It doesn't appear to be preserved in viewstate.

-Bill
 
G

Guest

in order to rebuild the tree/menu on postback, I still need to persist the
values used to create the menu to begin with...
therein looks to be my problem, i am losing what I have previously put into
viewstate before I ever get to the page load/page init...

as soon as I select a menu item, bam, everything I put in viewstate is gone...

before the new page load/page init...

suggestions?

thanks in advance.
 
B

BillE

I think if you use NavigateURL it is not a postback so what you add to
viewstate is gone.

I use the SelectedNodeChanged event of the treeview to load the value I want
into a temporary session variable. Then I call Response.Redirect to open
the content page. The content page retrieves the temporary session
variable.

I have a function in my master page to load my treeview. I can call this
function in the master page from the content page when it loads. It passes
the value it retrieved from the session variable to the function in the
master page.

Remember to set the VirtualPath attribute of the MasterType directive in the
content page, so you can call functions in the master page - like
'Master.LoadTreeview(id)'.

This is the way I do it, and it works fine. If there's a better way I hope
somebody posts it.

-Bill
 
M

Mark Rae

in order to rebuild the tree/menu on postback, I still need to persist the
values used to create the menu to begin with...
therein looks to be my problem, i am losing what I have previously put
into
viewstate before I ever get to the page load/page init...
as soon as I select a menu item, bam, everything I put in viewstate is
gone...
before the new page load/page init...

Well of course it has - you've just opened a new page! What ViewState are
you expecting to find...?
suggestions?

At the risk of repeating myself, I really do feel that you're doing this
backwards!

You are trying to use ViewState incorrectly - ViewState is for persisting
values WITHIN THE SAME PAGE across postbacks.

A MasterPage is NOT a page in the normal sense - it is a UserControl.

When your menu redirects from one aspx page to another (even if that menu
resides on a MasterPage), it's opening a new page - there's no ViewState at
this point because the page isn't being posted back You're wasting your time
trying to figure out where the ViewState has gone - there isn't any - it's a
newly opened page. The old page has gone and a new one is being opened - the
fact that the old page and the new page may both be ContentPages which use
the same MasterPage is COMPLETELY IRRELEVANT!

Having dynamic menus on MasterPages is really easy, but not the way you're
trying to do it...

If your ContentPage needs to control the menu on its MasterPage, then you
need to define some properties in the class behind the MasterPage and set
their values when the ContentPage loads...
 
M

Mark Rae

I think if you use NavigateURL it is not a postback so what you add to
viewstate is gone.

Well obviously - I think that's the fundamental issue that the OP can't
quite grasp...
I use the SelectedNodeChanged event of the treeview to load the value I
want into a temporary session variable. Then I call Response.Redirect to
open the content page. The content page retrieves the temporary session
variable.

Session variables, Bill? Surely not! What if the user does a Ctrl-N...? ;-)
I have a function in my master page to load my treeview. I can call this
function in the master page from the content page when it loads. It
passes the value it retrieved from the session variable to the function in
the master page.
Absolutely!

This is the way I do it, and it works fine. If there's a better way I
hope somebody posts it.

I wouldn't personnaly use Session for this - I'd have properties in the
class behind the MasterPage whose values would be set by the ContentPage -
but the effect is the same...
 
G

Guest

In my scenario I cannot set the property values until after the MasterPage
has been already loaded and a specific decision has been made to load that
particular menu, which will always be dynamic, and subject to change;
properties in code behind/base class/interface were my first choice, did not
work, their behavior works just like the ViewState does in this scenario, as
soon as a menu is selected the value is gone...

Not a big fan of session...

I just tried the new Asp.Net 2.0 Profile object...

This is the ticket...

It’s strongly typed and it will hang onto the values that I want to reuse on
the same MasterPage and its values live in the web config and can be accessed
from anywhere on the fly...

sorry for any semantics confusion...

Best regards.
 
G

Guest

also my content pages are not controlling the dynamic menus on the master
page they are running on or merged with; (the menus are part of the master)
the menu on the master page is deciding what content page to display in its
own content place holder.

best regards.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top