This is a migrated thread and some comments may be shown as answers.

PanelBar, TreeView, and XmlHttpPanel

5 Answers 98 Views
XmlHttpPanel
This is a migrated thread and some comments may be shown as answers.
Neil
Top achievements
Rank 1
Neil asked on 24 Nov 2010, 01:39 PM

The page has a panel bar which dynamically loads TreeViews as PanelItems.  To prevent losing the trees during a postback, a custom control is loaded in the XmlHttpPanel.  In order to get the correct control and pass all desired information, I need to access multiple custom attributes of the selected node.  Any suggestions on how to either pass or access the selected node server side (from within the "XmlHttpPanel_ServiceRequest" without performing a postback? 

Update to post: The trees are gone upon the service request as well and since the tree and nodes or not serializable the information cannot be stored in the viewstate either.  What was the point of making a control that loses its contents upon a postback?  Looks like the path will be to stuff everything into a long string for use as the "value" on the service call then parse out what's needed.  For such an impressive toolset overall, seems like the PanelBar is a tad lacking.  Unless of course, I missing the obvious which is always a possibility.

Below is an overly simplified view of what is being attempted.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  
<head runat="server">
    <title></title>
    <telerik:RadScriptBlock ID="RadScriptBlock1" runat="server">
        <script language="javascript" type="text/javascript">
            function NodeClicked(sender, args) {
                var node = args.get_node();
                var panel = $find("<%= RadXmlHttpPanel1.ClientID %>");
                panel.set_value(node.get_text());
            }
        </script>
    </telerik:RadScriptBlock>
</head>
<body>
    <form id="form1" runat="server">
    <telerik:RadScriptManager ID="RadScriptManager1" runat="server">
    </telerik:RadScriptManager>
    <table>
        <tr>
            <td>
                <telerik:RadPanelBar ID="RadPanelBar1" runat="server">
                </telerik:RadPanelBar>
            </td>
            <td>
                <telerik:RadXmlHttpPanel ID="RadXmlHttpPanel1" runat="server" OnServiceRequest="XmlHttpPanel_ServiceRequest">
                </telerik:RadXmlHttpPanel>
            </td>
        </tr>
    </table>
    </form>
</body>
</html>

public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                LoadRootContent();
        }
        private void LoadRootContent()
        {
            RadPanelItem myPanelItem = new RadPanelItem("Item 1");
            RadTreeView myTreeView = new RadTreeView();
            myTreeView.OnClientNodeClicked = "NodeClicked";
            //Build a node
            RadTreeNode node1 = new RadTreeNode("TreeNode 1");
            node1.Category = "Customers";
            node1.Attributes.Add("CustomerID", "123");
            myTreeView.Nodes.Add(node1);
            //Build another node
            RadTreeNode node2 = new RadTreeNode("TreeNode 2");
            node2.Category = "Prospects";
            node2.Attributes.Add("ProspectID", "456");
            myTreeView.Nodes.Add(node2);
  
            //Add the tree to the PanelItem - this could happen more than once for each PanelItem
            myPanelItem.Controls.Add(myTreeView);
            //Add the item to the PanelBar - this would occur for multiple items
            RadPanelBar1.Items.Add(myPanelItem);
        }
        protected void XmlHttpPanel_ServiceRequest(object sender, RadXmlHttpPanelEventArgs e)
        {
            string val = e.Value;
            if (val == "TreeNode 1")
            {
                RadXmlHttpPanel1.Controls.Add(LoadControl("Test1.ascx"));
            }
            if (val == "TreeNode 2")
                RadXmlHttpPanel1.Controls.Add(LoadControl("Test2.ascx"));
  
        }
    }

Any suggestions or thoughts are welcome.
Thanks in advance.

5 Answers, 1 is accepted

Sort by
0
Neil
Top achievements
Rank 1
answered on 24 Nov 2010, 06:32 PM
After much foul language and fussing, I feel pretty sheepish about how easy the solution actually was.  Below is the code that works for anyone else's reference.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  
<head runat="server">
    <title></title>
    <telerik:RadScriptBlock ID="RadScriptBlock1" runat="server">
        <script language="javascript" type="text/javascript">
            function NodeClicked(sender, args) {
                var node = args.get_node();
                var panel = $find("<%= RadXmlHttpPanel1.ClientID %>");
                var stringArray = node.get_attributes
                panel.set_value(node.toJsonString());
            }
        </script>
    </telerik:RadScriptBlock>
</head>
<body>
    <form id="form1" runat="server">
    <telerik:RadScriptManager ID="RadScriptManager1" runat="server">
    </telerik:RadScriptManager>
    <table>
        <tr>
            <td>
                <telerik:RadPanelBar ID="RadPanelBar1" runat="server">
                </telerik:RadPanelBar>
            </td>
            <td>
                <telerik:RadXmlHttpPanel ID="RadXmlHttpPanel1" runat="server" OnServiceRequest="XmlHttpPanel_ServiceRequest">
                </telerik:RadXmlHttpPanel>
            </td>
        </tr>
    </table>
    </form>
</body>
</html>

protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                LoadRootContent();
        }
        private void LoadRootContent()
        {
            RadPanelItem myPanelItem = new RadPanelItem("Item 1");
            RadTreeView myTreeView = new RadTreeView();
            myTreeView.OnClientNodeClicked = "NodeClicked";
            //Build a node
            RadTreeNode node1 = new RadTreeNode("TreeNode 1");
            node1.Category = "Customers";
            node1.Attributes.Add("CustomerID", "123");
            myTreeView.Nodes.Add(node1);
            //Build another node
            RadTreeNode node2 = new RadTreeNode("TreeNode 2");
            node2.Category = "Prospects";
            node2.Attributes.Add("ProspectID", "456");
            myTreeView.Nodes.Add(node2);
  
            //Add the tree to the PanelItem - this could happen more than once for each PanelItem
            myPanelItem.Controls.Add(myTreeView);
            //Add the item to the PanelBar - this would occur for multiple items
            RadPanelBar1.Items.Add(myPanelItem);
            RadPanelBar1.EnableViewState = true;
        }
        protected void XmlHttpPanel_ServiceRequest(object sender, RadXmlHttpPanelEventArgs e)
        {
            System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            RadTreeNode myNode = serializer.Deserialize<RadTreeNode>(e.Value);
  
            switch (myNode.Category)
            {
                case "Customers":
                    RadXmlHttpPanel1.Controls.Add(LoadControl("Test1.ascx"));
                    break;
                case "Prospects":
                    RadXmlHttpPanel1.Controls.Add(LoadControl("Test2.ascx"));
                    break;
            }
        }
0
Neil
Top achievements
Rank 1
answered on 01 Dec 2010, 09:53 PM
ok, so the RadTreeNode gets created but the attributes do not populate.  I'm guessing this is due to case sensitivity (just guessing after looking at the JSON string that gets generated.  It's the attributes that I really need.  Is there any one who can enlighten me?  Or am I going to have to parse the string myself and rebuild the node (or just use the data I recover)?
0
Accepted
Pero
Telerik team
answered on 02 Dec 2010, 04:55 PM
Hello Dave,

Apparently the JavaScriptSerializer does not correctly deserialize the Attributes collection object from the string provided. I tried capitalizing the first letter of "attributes" key, but again the Attributes did not get populated. So (I guess) the only way left is to manually populate the whole list.
For your convenience I have modified your code to populate the collection manually. Here is the modified code:

protected void XmlHttpPanel_ServiceRequest(object sender, RadXmlHttpPanelEventArgs e)
{
    System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    string value = e.Value;
 
    RadTreeNode myNode = serializer.Deserialize<RadTreeNode>(value);
 
    Dictionary<string, object> result = serializer.Deserialize<Dictionary<string, object>>(value);
    Dictionary<string, object> attributes = result["attributes"] as Dictionary<string, object>;
 
    foreach (string item in attributes.Keys)
    {
        myNode.Attributes.Add(item, attributes[item].ToString());
    }
 
    switch (myNode.Category)
    {
        case "Customers":
            int Checkit = myNode.Attributes.Count;
            RadXmlHttpPanel1.Controls.Add(new LiteralControl("Node 1 clicked:  " + result["attributes"]));
            break;
        case "Prospects":
            RadXmlHttpPanel1.Controls.Add(new LiteralControl("Node 2 clicked:  " + result["attributes"]));
            break;
    }
}


All the best,
Pero
the Telerik team
Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
0
Neil
Top achievements
Rank 1
answered on 02 Dec 2010, 05:09 PM
Thanks Pero, I had already created another method which is not as elegant as yours but will parse the JSON string without the need to bother with the deserialization.  I've included my code here for the convenience of others.  Also of note, do not assign a name of "ID" for an attribute as the JSON serialization process appears to strip that from the attributes list.  Make sure to append "ID" with something or use a different name all together.  It is important when manually parsing to leave the original string intact for the most part as there is no guarrantee that in future updates or calls the items contained in the string will be in the same order.  So mapping the original attributes of the object as well as any attribute which is actually an array is essential for continued success.

public class radExtenders
{
    public static RadTreeNode BuildNodeFromJSONstring(String myString)
    {
        RadTreeNode myNode = new RadTreeNode();
        //Get rid of Quotes
        myString = myString.Replace("\"", "");
        //Retrieve the original Node value
        int nodeValueStart = myString.IndexOf("value:");
        string myNodeString = myString.Remove(0, nodeValueStart + 6);
        int nodeValueEnd = myNodeString.IndexOf(",");
        myNode.Value = myNodeString.Substring(0, nodeValueEnd);
        //Retrieve category name
        int CategoryNameStart = myString.IndexOf("category:");
        string myCategoryString = myString.Remove(0, CategoryNameStart + 9);
        int CategoryNameEnd = myCategoryString.IndexOf(",");
        myNode.Category = myCategoryString.Substring(0, CategoryNameEnd);
        //Find then retrieve the attributes if any
        int AttribStart = myString.IndexOf("attributes:");
        if (AttribStart > -1)
        {
            string strAttribList = myString.Remove(0, AttribStart + 12);
            int AttribEnd = strAttribList.IndexOf("}");
            strAttribList = strAttribList.Substring(0, AttribEnd);
            while (strAttribList.Length > 0)
            {
                int NameFinder = strAttribList.IndexOf(":");
                string strName = strAttribList.Substring(0, NameFinder);
                strAttribList = strAttribList.Remove(0, NameFinder + 1);
                int ValueFinder = strAttribList.IndexOf(",");
                string strValue = string.Empty;
                if (ValueFinder > -1)
                {
                    strValue = strAttribList.Substring(0, ValueFinder);
                    strAttribList = strAttribList.Remove(0, ValueFinder + 1);
                }
                else
                {
                    strValue = strAttribList;
                    strAttribList = string.Empty;
                }
                myNode.Attributes.Add(strName, strValue);
                //Remove after testing
                if (strName == "ctgID")
                {
                    string stopHere = "StopHere";
                }
            }
        }
        //Find Text value for node
        int TextValueStart = myString.IndexOf("text:");
        string myTextString = myString.Remove(0, TextValueStart + 5);
        int TextValueEnd = myTextString.IndexOf(",");
        if (TextValueEnd > -1)
        {
            myNode.Text = myTextString.Substring(0, TextValueEnd);
        }
        else
        {
            myNode.Text = myTextString.Substring(0, myTextString.Length - 2);
        }
        return myNode;
    }
}
0
Pero
Telerik team
answered on 07 Dec 2010, 09:50 AM
Hello Dave,

Thank you for the additional information!

I will close this thread, and if you have other questions you can contact us at any time.

Greetings,
Pero
the Telerik team
Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
Tags
XmlHttpPanel
Asked by
Neil
Top achievements
Rank 1
Answers by
Neil
Top achievements
Rank 1
Pero
Telerik team
Share this question
or