Welcome Guest Search | Active Topics | Sign In | Register

Menu control data binding Options
Laurynas
Posted: Tuesday, October 5, 2010 4:50:04 AM
Rank: Advanced Member
Groups: Member

Joined: 3/23/2010
Posts: 35
Hello,

I've been struggling for some time to get a menu control derived from EO.Web (build 7.0.79.2) menu working correctly when data binding to an XmlDataSource. I am trying to save custom item data along with most of menu items and persist that data across postbacks using ViewState.

There are several problems, all of them boils down to that if I override any standard System.Web.UI.Control method (be it any of OnInit/OnLoad/OnPreRender, or even SaveViewState/LoadViewState), the menu control stops working correctly or even starts crashing.

So here is a (probably incomplete) list of problems:
1) When I override OnInit, automatic data binding stops working and additional code is required to handle data binding
2) If I override OnPreRender, control crashes when rendering. It crashes even if the only thing that overridden OnPreRender does is call base.OnPreRender. Stack trace:
[NullReferenceException: Object reference not set to an instance of an object.]
EO.Web.Internal.k.a(HtmlTextWriter A_0) +294
EO.Web.BaseNavigator.b(HtmlTextWriter A_0) +917
EO.Web.WebControlBase.o(HtmlTextWriter A_0) +54
EO.Web.WebControlBase.a(HtmlTextWriter A_0) +140
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) +163
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +32
System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) +51
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) +40
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.Page.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1266
3) If I override SaveViewState/LoadViewState, control forgets it's state between postbacks and menu items disappear. Even overridden methods that only call base implementation cause this.

This is the control I am using to test functionality.
~/App_Code/TestMenu.cs:
Code: C#
using System.Web.UI;
using EO.Web;
using System.Collections.Generic;
using System;
using System.Xml;

namespace Test
    {
    public class TestMenu : EO.Web.Menu
        {
        class ItemData
            {
            public int Custom
                {
                get;
                set;
                }
            }

        Dictionary<string, ItemData> m_customData = new Dictionary<string, ItemData> ();

        // Attaching event handlers in constructor because overriding OnInit prevents menu from data binding automatically
        public TestMenu ()
            {
            this.ItemDataBound += TestMenu_ItemDataBound;
            }

        /*
        // Overriding OnInit prevents control from automatically data binding to datasource
        // That's why I need OnPreRender/PreRender event handler and DataBindingPerformed property
        protected override void OnInit (EventArgs e)
            {
            this.ItemDataBound += TestMenu_ItemDataBound;
            //this.PreRender += TestMenu_PreRender;
            base.OnInit (e);
            }

        // Workaround for crashing OnPreRender
        void TestMenu_PreRender (object sender, EventArgs e)
            {
            if (!this.DataBindingPerformed)
                this.DataBind ();
            }

        protected override void OnDataBinding (EventArgs e)
            {
            this.DataBindingPerformed = true;
            base.OnDataBinding (e);
            }

        bool DataBindingPerformed
            {
            get
                {
                object o = ViewState["DataBindingPerformed"];
                return (null == o) ? false : (bool)o;
                }
            set
                {
                ViewState["DataBindingPerformed"] = value;
                }
            }

        // Overriding OnPreRender causes EO.Web.Menu to crash in Render stage
        protected override void OnPreRender (EventArgs e)
            {
            if (!this.DataBindingPerformed)
                this.DataBind ();

            base.OnPreRender (e);
            }
        */

        void TestMenu_ItemDataBound (object sender, NavigationItemEventArgs e)
            {
            XmlNode itemSource = (XmlNode)e.MenuItem.DataItem;
            ItemData itemData = new ItemData ();
            itemData.Custom = int.Parse (itemSource.Attributes["Custom"].Value);
            m_customData[e.MenuItem.ItemID] = itemData;
            }

        // Overriding LoadViewState/SaveViewState disables control's view state management and menu items disappear after a postback
        protected override void LoadViewState (object savedState)
            {
            if (null == savedState)
                return;

            Triplet viewState = (Triplet)savedState;
            base.LoadViewState (viewState.First);

            string[] IDs = (string[])viewState.Second;
            int[] custom = (int[])viewState.Third;
            int index = 0;
            foreach (string id in IDs)
                {
                ItemData itemData = new ItemData ();
                itemData.Custom = custom[index];
                m_customData.Add (IDs[index], itemData);
                index++;
                }
            }

        protected override object SaveViewState ()
            {
            object o = base.SaveViewState ();
            string[] IDs = new string[m_customData.Count];
            int[] custom = new int[m_customData.Count];
            int index = 0;
            foreach (KeyValuePair<string, ItemData> pair in m_customData)
                {
                IDs[index] = pair.Key;
                custom[index] = pair.Value.Custom;
                index++;
                }
            
            return new Triplet (o, IDs, custom);
            }
        }
    }


~/menu.aspx:
Code: HTML/ASPX
<%@ Page Language="C#" Debug="true" %>

<%@ Register Namespace="Test" TagPrefix="test" %>
<%@ Register Assembly="EO.Web" Namespace="EO.Web" TagPrefix="eo" %>

<!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>Menu test </title>
    <meta http-equiv="X-UA-Compatible" content="IE=8" />
</head>
<body>
    <form runat="server">
    <asp:XmlDataSource runat="server" ID="datasource" XPath="/Menu/*">
        <Data>
            <Menu>
                <Item ID="test1" Label="test1_label" Custom="1">
                    <Item ID="test1_1" Label="test11_label" Custom="11"></Item>
                    <Item ID="test1_2" Label="test12_label" Custom="12"></Item>
                    <Item ID="test1_3" Label="test13_label" Custom="13"></Item>
                </Item>
                <Item ID="test2" Label="test2_label" Custom="2">
                    <Item ID="test2_1" Label="test21_label" Custom="21"></Item>
                    <Item ID="test2_2" Label="test22_label" Custom="22"></Item>
                </Item>
                <Item ID="test3" Label="test3_label" Custom="3"></Item>
            </Menu>
        </Data>
    </asp:XmlDataSource>
    <test:TestMenu runat="server" ControlSkinID="Office2003" ID="menu1" DataSourceID="datasource">
        <TopGroup>
            <Bindings>
                <eo:DataBinding Property="ItemID" DataField="@ID" />
                <eo:DataBinding Property="Text" DataField="@Label" />
            </Bindings>
        </TopGroup>
    </test:TestMenu>
    <asp:Button runat="server" Text="post" />
    </form>
</body>
</html>
eo_support
Posted: Tuesday, October 5, 2010 12:49:01 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

We tested your code at here and it seems to be working fine. What version are you running?

Thanks!
Laurynas
Posted: Wednesday, October 6, 2010 2:58:13 AM
Rank: Advanced Member
Groups: Member

Joined: 3/23/2010
Posts: 35
eo_support wrote:
Hi,

We tested your code at here and it seems to be working fine. What version are you running?

Thanks!


I'm using EO.Web version 7.0.79.2

It's strange that you can't reproduce these problems. The sample I gave you loads fine, but menu items disappear after clicking "post" button. Other problems can be reproduced by uncommenting appropriate parts of the code in TestMenu.cs

I also tried it with version 8.0 and I still see the same problems.
eo_support
Posted: Wednesday, October 6, 2010 9:02:18 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

Can you send the test project in zip format to us? We will PM you as to where to send.

Thanks!
Laurynas
Posted: Thursday, October 7, 2010 12:23:38 AM
Rank: Advanced Member
Groups: Member

Joined: 3/23/2010
Posts: 35
eo_support wrote:
Hi,

Can you send the test project in zip format to us? We will PM you as to where to send.

Thanks!


Hello,

I have sent you zipped files yesterday, did you have a chance to look at them?


Thanks,
Laurynas
eo_support
Posted: Thursday, October 7, 2010 8:29:55 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Yes. We did receive it and found the problem. We will provide you a new build today that should fix the problem.

Thanks!
eo_support
Posted: Thursday, October 7, 2010 1:18:41 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

We have posted a new build that should fix this issue for you. Please see your private message for the download location.

Thanks!
Laurynas
Posted: Friday, October 8, 2010 2:08:28 AM
Rank: Advanced Member
Groups: Member

Joined: 3/23/2010
Posts: 35
eo_support wrote:
Hi,

We have posted a new build that should fix this issue for you. Please see your private message for the download location.

Thanks!


The data binding and view state problems are fixed, though overriding OnPreRender still produces the crash I described earlier.

Could you fix these problems to version 7.0 of EO.Web controls? The license we have does not work with 8.0 builds.


Thanks,
Laurynas

eo_support
Posted: Friday, October 8, 2010 12:38:21 PM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
Hi,

We have just posted another build that should also fix OnPreRender for you.

I believe you license should cover this build because your purchase includes a one year free upgrade period. You will need to go to your license key page to download a new license file for the new version.

Thanks!
Laurynas
Posted: Monday, October 11, 2010 8:16:01 AM
Rank: Advanced Member
Groups: Member

Joined: 3/23/2010
Posts: 35
Thanks!
eo_support
Posted: Monday, October 11, 2010 9:43:57 AM
Rank: Administration
Groups: Administration

Joined: 5/27/2007
Posts: 24,194
You are welcome. Please feel free to let us know if you run into another other issues.

Thanks


You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.