|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
I'm not sure how to accomplish what I'm trying to do.
I would like to use a databound context menu to create a checkbox list. I have implemented a TemplateItem to add a checkbox to each MenuItem. Now I need to be able to open the menu, select any number of checkbox items in the menu and then when I click off of the open menu, have it submit the checked values (if any) or do nothing if no checkboxes were clicked.
Is it possible to force postback when the menu loses focus? How do I capture the event to process the checkboxes?
Thanks...
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi Scott,
Unfortunately no. The menu does not have any support for you to trigger a postback when losing focus.
In order to collect the check box value on the server side, you would need to use something similar to this:
CheckBox cb = (CheckBox)Menu1.Items[0].CustomItemInstance.FindControl("CheckBox1");
Thanks
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
Do you know of any other way to implement the menu so that it will accept multiple selections?
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, You may want to consider using TreeView. A TreeView has built-in checkbox support: http://www.essentialobjects.com/Demo/Default.aspx?path=TreeView\_i1\_i3Thanks
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
As it turns out the CustomItem is causing an error on postback. I have a simple recordset bound to the menu (ID, Name). When the TopGroup/TemplateItem/CustomItem code is removed everything works fine on postback. However when I include the code to embed a checkbox control in the menuItems I receive the following error on cmnuMain1A.DataBind() during postback:
Key cannot be null. Parameter name: key
Do you know what causes this error? I can see that the datatable I am binding to contains data so I'm not sure what else might cause this. Again, the error goes away when I remove the TemplateItem. Thanks...
<eo:ContextMenu ID="cmnuMain1A" runat="server" ControlSkinID="Style1" SubMenuIconUrl="Blank" RaisesServerEvent="True" EnableScrolling="True" OnItemDataBound="cmnuMain_ItemDataBound" ClientSideOnMouseOut="submitMenu"> <TopGroup> <TemplateItem> <CustomItem> <asp:CheckBox ID="chkMain1A" Runat="server" Text='<%#((System.Data.DataRowView)Container.DataItem)["Name"]%>' Value='<%#((System.Data.DataRowView)Container.DataItem)["ID"]%>'></asp:CheckBox> </CustomItem> </TemplateItem> </TopGroup> </eo:ContextMenu>
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi, Do you have the detailed call stack information? Also, since you are already handling OnItemDataBound, you can do the data binding inside that function as well. You can do:
Code: C#
System.Data.DataRowView dataRow =
(System.Data.DataRowView)cmnuMain1A.DataItem;
CheckBox cb = (CheckBox)e.CustomItem.FindControl("chkMain1A");
cb.Text = dataRow["Name"].ToString();
Please let us know if that works. Thanks
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
Moving the checkbox databinding to the OnItemDataBound function didn't change anything. Here's the stack trace...
mscorlib.dll!System.Collections.Hashtable.Remove(object key) + 0x20d bytes EO.Web.DLL!EO.Web.BaseNavigator.c(EO.Web.NavigationItem A_0 = {EO.Web.MenuItem}) + 0x9b bytes EO.Web.DLL!EO.Web.NavigationItem.a(EO.Web.BaseNavigator A_0 = null) + 0x2a9 bytes EO.Web.DLL!EO.Web.NavigationItemCollection.a(EO.Web.NavigationItem A_0 = {EO.Web.MenuItem}) + 0x20 bytes EO.Web.DLL!EO.Web.NavigationItemCollection.b() + 0x95 bytes EO.Web.DLL!EO.Web.NavigationItemCollection.a.a() + 0x1c bytes EO.Web.DLL!EO.Web.Internal.aw.c() + 0xab bytes EO.Web.DLL!EO.Web.NavigationItemCollection.Clear() + 0x1c bytes xt34zyv-!EO.Web.Internal.gw.a(EO.Web.NavigationItemGroup A_0 = {EO.Web.MenuGroup}) + 0x114 bytes EO.Web.DLL!EO.Web.BaseNavigator.a(EO.Web.NavigationItemGroup A_0 = {EO.Web.MenuGroup}) + 0x29 bytes EO.Web.DLL!EO.Web.NavigationItemGroup.b() + 0x72 bytes EO.Web.DLL!EO.Web.NavigationItemGroup.DataBind() + 0x19 bytes EO.Web.DLL!EO.Web.BaseNavigator.e() + 0x184 bytes EO.Web.DLL!EO.Web.DataBoundControl.OnDataBinding(System.EventArgs e = {System.EventArgs}) + 0x52 bytes EO.Web.DLL!EO.Web.BaseNavigator.DataBind() + 0x21 bytes > DeepDomain.RulesEngine.Application.DLL!DD.RulesEngine.UI.Controls.Value.bindCmnuMain1A() Line 475 + 0xb bytes C# DeepDomain.RulesEngine.Application.DLL!DD.RulesEngine.UI.Controls.Value.Page_Load(object sender = {ASP.controls_value_ascx}, System.EventArgs e = {System.EventArgs}) Line 179 + 0x7 bytes C# System.Web.RegularExpressions.dll!System.Web.Util.CalliHelper.EventArgFunctionCaller(System.IntPtr fp, object o, object t, System.EventArgs e) + 0x10 bytes System.Web.dll!System.Web.Util.CalliEventHandlerDelegateProxy.Callback(object sender, System.EventArgs e) + 0x23 bytes System.Web.dll!System.Web.UI.Control.OnLoad(System.EventArgs e) + 0x64 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x30 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Control.LoadRecursive() + 0x84 bytes System.Web.dll!System.Web.UI.Page.ProcessRequestMain(bool includeStagesBeforeAsyncPoint = true, bool includeStagesAfterAsyncPoint = true) + 0x426 bytes System.Web.dll!System.Web.UI.Page.ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint = true) + 0x67 bytes System.Web.dll!System.Web.UI.Page.ProcessRequest() + 0x57 bytes System.Web.dll!System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext context) + 0x13 bytes System.Web.dll!System.Web.UI.Page.ProcessRequest(System.Web.HttpContext context) + 0x32 bytes App_Web_ruleedit.aspx.cdcab7d2.b7lgmkab.dll!ASP.ruleedit_aspx.ProcessRequest(System.Web.HttpContext context = {System.Web.HttpContext}) + 0x2f bytes C# System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 0x130 bytes System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.CallHandlerExecutionStep}, ref bool completedSynchronously = true) + 0x41 bytes System.Web.dll!System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(System.Exception error) + 0x188 bytes System.Web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object extraData) + 0x8d bytes System.Web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest wr = {Microsoft.VisualStudio.WebHost.Request}) + 0x1ab bytes System.Web.dll!System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest wr) + 0x62 bytes System.Web.dll!System.Web.HttpRuntime.ProcessRequest(System.Web.HttpWorkerRequest wr) + 0x38 bytes WebDev.WebHost.dll!Microsoft.VisualStudio.WebHost.Request.Process() + 0x113 bytes WebDev.WebHost.dll!Microsoft.VisualStudio.WebHost.Host.ProcessRequest(Microsoft.VisualStudio.WebHost.Connection conn = {System.Runtime.Remoting.Proxies.__TransparentProxy}) + 0x5c bytes [Appdomain Transition] WebDev.WebHost.dll!Microsoft.VisualStudio.WebHost.Server.OnSocketAccept(object acceptedSocket) + 0x86 bytes mscorlib.dll!System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(object state) + 0x2f bytes mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x43 bytes [Native to Managed Transition] [Managed to Native Transition] mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0xa7 bytes mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x92 bytes mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(object state) + 0x6c bytes
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi Scott,
This appear to be a bug that we have recently fixed. Please download the latest build that we just posted (2007.2.16) and see if it fixes the problem.
Thanks
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
I have installed the latest build and the problem still occurs. I have created a sample page that I'd like to send to you so you can see the issue and tell me if it's a bug or if I'm doing something wrong. It has a left-click context menu and a button to cause postback. When the CustomItem is on the page and the checkboxes are added to each MenuItem clicking the button throws the error. When the CustomItem checkboxes are removed, the error goes away. Can you PM me an email address that I can send this to? I really need to figure out what's going on because this issue is holding up my project.
Thanks--I appreciate the great support you guys provide...
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
It turns out that I'm an idiot and forgot to update the reference to EO.Web.DLL so I was still using the old build. Once I changed the reference to point to the latest build the problem was fixed. Thanks again for the quick resolution.
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
I hope you can help with this although I don't think I can explain what's going on very well.
I am dynamically adding ContextMenus to PlaceHolder controls and then adding these PlaceHolders to the TableCells and TableRows of a layout Table for display. The problem is that recreating these controls on each postback is a performance problem which gets worse as I add more controls to the page on each successive postback. The problem is magnfied because since these are dynamic controls I have to add them to the page twice--once during Init so the controls exist in time to participate in the LoadPostData method and once again during PreRender to update my controls to reflect the user's input.
So I've decided to cache my layout Table and retrieve it from the cache on successive postbacks so I then only have to add newly created controls to the layout Table and not have to recreate all previously added rows. However now when I retrieve my layout Table from the cache and try to add a new row I receive an error from eo.web.dll. I'm hoping you will be able to point me in a direction after seeing the exception because I'm not really sure what's going on. When I remove the caching code and always recreate all controls on postback, the error goes away.
Here's the error--I appreciate any help you can provide...
System.NullReferenceException was unhandled by user code Message="Object reference not set to an instance of an object." Source="EO.Web" StackTrace: at EO.Web.Head.a(Control A_0) at EO.Web.Head.a(Control A_0) at EO.Web.Internal.bn.j() at EO.Web.Internal.bn.h() at EO.Web.WebControlBase.OnInit(EventArgs e) at EO.Web.DataBoundControl.c(EventArgs A_0) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.AddedControl(Control control, Int32 index) at System.Web.UI.ControlCollection.Add(Control child) at System.Web.UI.WebControls.Table.RowControlCollection.Add(Control child)
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
Hi Scott,
You won't be able to cache our controls. Browser can cache on the client side, but caching our controls on the server side causes problems because our controls rely a full "normal" page cycle to function properly.
You should also avoid dynamically adding ContextMenu controls. While technically you can place multiple ContextMenu controls in the same page, it is usually not necessary to do so, because at any given time only one ContextMenu will be active. Thus you would generally put a single context menu on the page and display it for different controls, sometimes you may want to modify the context menu on the client side when it is shown by different element. You can find a sample in our demo project demonstrating this technique.
Thanks
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
Okay, I have a table that has two rows in it. Each row has one label and each of the labels are bound to the same ContextMenu. How can I add the rowID (1 or 2) to the ContextMenu so I can tell in the menu's OnClick server-side event handler which row's menu instance was clicked? I tried adding a custom attribute during control creation but it will always contains the rowID of the last menu row added (in this case rowID 2). Thanks again...
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
|
|
Rank: Member Groups: Member
Joined: 5/30/2007 Posts: 15
|
I am already using eo_ShowContextMenu to display the context menu. What I'm unable to do is add any information to the menu that will get passed to the menu's onclick event handler. So in the example you linked to, how would you pass the recID to the menu's onclick event handler? I don't want to change any items in the menu--both of my menus should contain the exact same list of items/values--I just need to know if menu instance 1 was clicked or menu instance 2 was clicked. Since they are both instances of the same menu with the same onclick event handler, how do I tell which menu's event I am processing?
Thanks...
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,194
|
You can use a hidden input field to pass the value back and then use Page.Request.Form["your_hidden_input_field_name"] to get the value you stored in the hidden field.
|
|