Rank: Advanced Member Groups: Member
Joined: 3/23/2010 Posts: 35
|
Hello, I've been struggling with ContextMenu control added to a user control (.ascx) - it is never binding when used this way and the user control is loaded via Page.LoadControl. Everything works fine when using ContextMenu control directly in the .aspx page or when using any ASP data bound control, like the ASP Menu in test.ascx. Am I missing something here or is this a bug in ContextMenu? DataBind.aspx:
Code: HTML/ASPX
<%@ Page Language="C#" Debug="true" %>
<script runat="server">
void OnPreRender (object sender, EventArgs e)
{
Control testControl = Page.LoadControl ("~/test.ascx");
test.Controls.Add (testControl);
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>DataBind test</title>
</head>
<body>
<form runat="server">
<asp:PlaceHolder runat="server" ID="test" OnPreRender="OnPreRender"></asp:PlaceHolder>
</form>
</body>
</html>
test.ascx:
Code: HTML/ASPX
<%@ Control Language="C#" AutoEventWireup="true" %>
<%@ Register TagPrefix="eo" Assembly="EO.Web" Namespace="EO.Web" %>
<asp:XmlDataSource runat="server" ID="menuSource" XPath="/*/*">
<Data>
<Menu>
<MenuItem title="test1">
<MenuItem title="test2">
<MenuItem title="test3"></MenuItem>
</MenuItem>
</MenuItem>
<MenuItem title="test4"></MenuItem>
</Menu>
</Data>
</asp:XmlDataSource>
<eo:ContextMenu runat="server" DataSourceID="menuSource" ContextControlID="tree">
</eo:ContextMenu>
<asp:Menu runat="server" DataSourceID="menuSource"></asp:Menu>
<asp:TreeView runat="server" ID="tree" DataSourceID="menuSource">
</asp:TreeView>
EDIT: Updated DataBind.aspx source. Data binding does not work when loading user controls with Page.LoadControl. Thanks, Laurynas
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, Please add the following code into the user control's Page_Load handler:
Code: C#
ContextMenu1.ContextControlID = tree.ClientID;
ContextMenu1.DataBind();
The first line is necessary because ContextControlID is the full ID of the client DOM element, not the server control's ID. The server control's ID and ClientID is the same without user control, but they are different when you use a user control. The second line is needed if the menu is dynamically loaded. Thanks!
|
Rank: Advanced Member Groups: Member
Joined: 3/23/2010 Posts: 35
|
This is the workaround I currently use, but why is it not working like any other data bound control? Data binding manually throws away the benefits of caching and rebinding only when data source changes. The ASP.NET life cycle overview also suggests that controls with DataSourceID set should bind automatically - see http://msdn.microsoft.com/en-us/library/ms178472.aspx and http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.basedataboundcontrol.datasourceid.aspx
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi,
Yes. We are aware of that. The menu (and context menu) does automatically bind to data source if it is inserted into the page before Page_Load, this is why if you place the menu statically in the page it works fine. It will also work if you dynamically load the control inside Page_Init. But if the menu is dynamically loaded in or after Page_Load, then it won't automatically bind to the data source.
I believe this is an implementation restriction. Because it is required that you load your control before Page_Load (usually inside Page_Init) in order to have server side event working, this is usually not a problem. For example, if you place a standard ASP.NET Button inside your test.ascx, you will NOT be able to handle that button's server side click event because you loaded the user control too late. Because unable to handle server event is a big issue, so user often find dynamic loading after Page_Load is not as useful.
If possible you can change your OnPreRender to OnInit, that way you will no longer need to call contextMenu1.DataBind() explicitly. (Note that you will still need the first line that sets the ContextControlID property). We will look into the issue at the same time to see if we can enable automatic binding after Page_Load.
Thanks!
|