Using .Net 2.0 and System.Web.UI.WebControls.Treeview with SQL Reporting Services 2005 for navigation and display.

I spent several hours sifting through article after article about how to build tree navigations dynamically.  They assumed that the order of the data coming in was 'orderly' and that you were usually using the IE Web Control toolkit which is a .Net 1.0 package.  In our environment 2.0+, that would not work for us and we needed to ensure browser compatibility.  Thanks to a colleagues suggestion of recursion, I came up with the following code below.  It's length is due to all the detailed commenting.  Feel free to comment on it, any positives or negatives?  It seems to work well and we have yet to find a way to break it.  Enjoy!

 

The code assumes you have a page called 'default.aspx' and that you have added one treeview to it labeled TreeView1.  You can substitute your sql server info as necessary in the code behind:

using System;
using System.Data;
using System.Configuration;
using System.Security.Cryptography;
using System.Text;
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;
using DW_SQL_ReportingService_TST;  //Substitue your webrefernce to your SQL Server Reporting Services


public partial class _Default : System.Web.UI.Page
{
    ReportingService objRepSrvc;
    CatalogItem[] objCatalogItems;
    protected static char pathSeparator = '/';
    protected static char[] pathSeparatorArray = { pathSeparator };
    protected static string pathSeparatorString = new string(pathSeparator, 1);


    protected void Page_Load(object sender, EventArgs e)
    {

        GetReportStructure();
    }

    /// <summary>
    /// Instantiate a new ReportingService object with specific credentials.  Then provide the
    /// reportpath to the ListChildren method.  This will return a collection of CatalogItems containing
    /// your report links. 
    /// </summary>
    private void GetReportStructure()
    {

        objRepSrvc = new ReportingService();
        objRepSrvc.Credentials = new System.Net.NetworkCredential("userid", "password", "domainname");
       
        /* We subtract one from the ReportPath variable here since it ends with a forward slash.  Our path
         * statement must be /dirA/DirB - without the ending slash
         * In addition, we also set the recursive flag to true indicating we want all subdirectories
         */
        objCatalogItems = objRepSrvc.ListChildren(ReportPath.Remove(ReportPath.Length - 1), true);

        BuildTree(objCatalogItems);

    }

    private void GetReportStructure(string path)
    {
        objRepSrvc = new ReportingService();

    }

    /// <summary>
    /// This method begins the process of putting our report paths into a usable form.
    /// </summary>
    /// <param name="objCatalogItems"></param>
    private void BuildTree(CatalogItem[] objCatalogItems)
    {
       
        // Iterate through each CatalogItem in your collection
        foreach (CatalogItem item in objCatalogItems)
        {
            // Since we want to use only Report Items we specify that as the Type.
            // In addition we also only want to use reports that are not hidden.  A
            // hidden report is often a drilldown or child report that needs parameters
            // from a prior report; therefore; only show reports not hidden.
            if (item.Type == ItemTypeEnum.Report && (!item.Hidden))
            {
                // Pull the current items complete path and strip off the beginning
                // portion which includes the ReportPath.  Then assign it to a string variable
                string path = item.Path.Remove(0, ReportPath.Length);
                // Split the path string by our previously assigned PathSeparatorArray and put
                // the values into a string array
                string[] tokens = path.Split(PathSeparatorArray);
                // Pass in our new string array and the collection of nodes from our Treeview on
                // our aspx page.
                BuildNodesFromTokens(tokens, TreeView1.Nodes);
               
            }
        }
   }

    /// <summary>
    /// This method is the first step in actually building our tree node collection.
    /// </summary>
    /// <param name="tokens">A string array containing our report and pathing parts</param>
    /// <param name="nodes">A collection of nodes from our treeview</param>
    private void BuildNodesFromTokens(string[] tokens, TreeNodeCollection nodes)
    {
        // Create a new string array that can hold our original string array values - 1.  The
        // reason for this is to begin shrinking our string array one by one.
        string[] newtoks = new string[tokens.Length - 1];
        // Check for any current nodes on the page
        if (nodes.Count > 0)
        {
            // Since nodes currently exists, we need to check to see if any of the current
            // nodes match the next value of tokens which we'll use to create a node.
           
            // Instantiate an integer variable to act as a counter
            int matchFound = 0;
            // Loop through each node already on the page
            foreach (System.Web.UI.WebControls.TreeNode tr in nodes)
            {
                // Compare the current node text with the current value of index 0 in our
                // string array.  If there is a match then assign all but the first value of
                // our original string array to our new string array - newtoks.
                if (tokens[0].Equals(tr.Text))
                {
                    for (int i = 0; i < newtoks.Length; i++)
                    {
                        newtoks[i] = tokens[i + 1];
                    }
                    // Increment counter
                    matchFound++;
                    // Pass the new string array, which is one less than original, and the current
                    // node to AddNode method.
                    AddNode(newtoks, tr);
                }

            }
            // If no match was found in the foreach loop
            if (matchFound == 0)
            {
                // Add a new node to the page and use the index 0 value of the tokens (original)
                // string array. 
                nodes.Add(new System.Web.UI.WebControls.TreeNode(tokens[0]));

                // Check to see if we have more than one value (indicating additional levels or depth)
                if (tokens.Length - 1 > 0)
                {

                    // Set the SelectAction of our last node, which is the new one we just created, to
                    // be None.  This prevents the folders from being links with a URL action.  We
                    // simply want it to be a + or - symbol indicating if we can expand or collapse the
                    // folder.
                    nodes[nodes.Count - 1].SelectAction = TreeNodeSelectAction.None;
                    // Assing all but the first value of tokens, our original string array to the newly
                    // created newtoks array.
                    for (int i = 0; i < newtoks.Length; i++)
                    {
                        newtoks[i] = tokens[i + 1];
                    }
                    // Since we just created a new 'parent' node, we'll pass any
                    // existing string array values to the AddChild method to build.  We can
                    // do this since we know that the parent node had not previously existed.  Therefore
                    // no new checks for existence are needed.
                    AddChild(newtoks, nodes[nodes.Count - 1]);
                }
                else
                {
                    // Since this was the last link, get the last node added (use Count - 1) & set it's value, url, and target window when clicked.
                    nodes[nodes.Count - 1].Value = Server.UrlEncode(String.Join(PathSeparatorString.ToString(), tokens));
                    nodes[nodes.Count - 1].Target = "_blank";
                    nodes[nodes.Count - 1].NavigateUrl = "./ReportViewer/ReportViewer.aspx?Report=" + ReportPath + nodes[nodes.Count - 1].ValuePath;
                }



            }
        }
        else
        {
            // Since no nodes currently exists we can safely add a new node using the index 0 value
            // of tokens.
            nodes.Add(new System.Web.UI.WebControls.TreeNode(tokens[0]));

            // Check to see if we have more than one value (indicating additional levels or depth)
            if (tokens.Length - 1 > 0)
            {
                // Set the SelectAction of our last node, which is the new one we just created, to
                // be None.  This prevents the folders from being links with a URL action.  We
                // simply want it to be a + or - symbol indicating if we can expand or collapse the
                // folder.
                nodes[nodes.Count - 1].SelectAction = TreeNodeSelectAction.None;
                // Assing all but the first value of tokens, our original string array to the newly
                // created newtoks array.
                for (int i = 0; i < newtoks.Length; i++)
                {
                    newtoks[i] = tokens[i + 1];
                }
                // Since we just created a new 'parent' node, we'll pass any
                // existing string array values to the AddChild method to build.  We can
                // do this since we know that the parent node had not previously existed.  Therefore
                // no new checks for existence are needed.
                AddChild(newtoks, nodes[nodes.Count - 1]);
            }
            else
            {
                // Since this was the last link, get the last node added (use Count - 1) & set it's value, url, and target window when clicked.
                nodes[nodes.Count - 1].Value = Server.UrlEncode(String.Join(PathSeparatorString.ToString(), tokens));
                nodes[nodes.Count - 1].Target = "_blank";
                nodes[nodes.Count - 1].NavigateUrl = "./ReportViewer/ReportViewer.aspx?Report=" + ReportPath + nodes[nodes.Count - 1].ValuePath;

            }
        }
    }

    /// <summary>
    /// This method is used to determine if we need to create a new node or go another level deeper.
    /// </summary>
    /// <param name="tokens">A string array containing our pathing (folder structure)</param>
    /// <param name="node">A specific tree node from our TreeView on the aspx page</param>
    private void AddNode(string[] tokens, System.Web.UI.WebControls.TreeNode node)
    {
        // Instantiate a newtoks string array to null;
        string[] newtoks = null;

        // Check the token length and if not equal to zero, go ahead and assign the newtoks array length
        // to the tokens length - 1.  We perform this check because, while unlikely, if we ever got duplicate
        // reports in the same exact position we would cycle through and end up with an index out of range
        // exception.  You'll see this as we go on.
        if (tokens.Length != 0)
        {
         newtoks = new string[tokens.Length - 1];
        }
       
        // Does the current node already have children (either folders or reports)
        if (node.ChildNodes.Count > 0)
        {
            // Since there were children, now we check each child node to see if it's
            // text property matches index 0 of the string array - tokens.

            // Instantiate a integer variable as a counter
            int matchFound = 0;
            // Loop through each node in the current node's child collection.
            foreach (System.Web.UI.WebControls.TreeNode tr in node.ChildNodes)
            {
                // Does the current child node match the string array index 0 value
                if (tokens[0].Equals(tr.Text))
                {
                    // Since there was a match, load the newtoks string array with
                    // all but the first value of the 'tokens array'
                    for (int i = 0; i < newtoks.Length; i++)
                    {
                        newtoks[i] = tokens[i + 1];
                    }
                    // Increment our counter since match was found.
                    matchFound++;
                    // Use recursive call to the AddNode method again passing in the next value
                    // of the string array and the current node.
                    AddNode(newtoks, tr);
                }
            }
            // Check if a match was found
            if (matchFound == 0)
            {
                // Since no match was found pass the current values of the tokens array and the current
                // node to the AddChild method.
                AddChild(tokens, node);
            }

        } else if (newtoks != null) {

            // We check to see if newtoks is null or not.  This is due to the AddNode method potentially allowing
            // a token initialized with 0 size to be sent.  If that is the case, and we try to pass that on to the
            // AddChild method, we'll get an index out of bounds exception.  To avoid that, we have the newtoks
            // array instantiated to an actual array of size only if tokens.length-1 is not 0.  I was able to
            // reproduce this by manually creating duplicate string arrays.  You, in theory, should not be able to
            // have duplicate reports or folders at the same level, however, in case you do we can accomodate it
            // by including this conditional.
           
            // Since there were no child nodes of the current node, we will place a call to the
            // AddChild method.
            AddChild(tokens, node);
        }

    }

    /// <summary>
    /// This method will actually create the node and link properties of the last level of each node.
    /// </summary>
    /// <param name="tokens">A string array containing our pathing (folder structure)</param>
    /// <param name="node">A specific tree node from our TreeView on the aspx page</param>
    private void AddChild(string[] tokens, System.Web.UI.WebControls.TreeNode node)
    {
            // Since we know this is a new child, we add a new child to the current node and assign it's
            // text property the value of index 0 in the string array
            node.ChildNodes.Add(new System.Web.UI.WebControls.TreeNode(tokens[0]));
           
            // Check to see if there is more than one value in the string array
            if (tokens.Length - 1 > 0)
            {
                // Since there is more than one vale in the array, create a new array called
                // newtoks and assign it the same size of tokens - 1.  We do this because
                // we no longer the first value in tokens since we have just used it to create
                // a new child node.
                string[] newtoks = new string[tokens.Length - 1];
                for (int i = 0; i < newtoks.Length; i++)
                {
                    newtoks[i] = tokens[i + 1];
                }
                // Since there are additional children under the newly created child, we know it's not a
                // report but is a folder.  As a result, we set it's SelectAction to none so that it's displayed
                // as a regular folder level label with nothing more than the + or - to expand/collapse.
                node.ChildNodes[node.ChildNodes.Count - 1].SelectAction = TreeNodeSelectAction.None;
                // Pass the newtoks array and the newly created childnode through a recursive call to AddChild.
                AddChild(newtoks, node.ChildNodes[node.ChildNodes.Count - 1]);
               
            }
            else
            {
                // The array only has one value indicating that this is the final level/report.

                // Since this was the last link, get the last node added (use Count - 1) & set it's value, url, and target window when clicked.
                node.ChildNodes[node.ChildNodes.Count - 1].Value = Server.UrlEncode(String.Join(PathSeparatorString.ToString(), tokens));
                node.ChildNodes[node.ChildNodes.Count - 1].Target = "_blank";
                node.ChildNodes[node.ChildNodes.Count - 1].NavigateUrl = "./ReportViewer/ReportViewer.aspx?Report=" + ReportPath + node.ChildNodes[node.ChildNodes.Count - 1].ValuePath;//Server.UrlEncode(objCrypt.Encrypt(ReportPath + node.ChildNodes[node.ChildNodes.Count - 1].Value));
            }


    }


    public static string ReportServer
    {
            // Substitue with whatever your SqlReportingServerName is
        get { return "http://SqlReportingServerName/Reports"; }
    }

    public static string ReportPath
    {
        get
        {   // Substitue with whatever your folder structure starts with
            return "/Sales/Field/";
        }
    }

    public static char[] PathSeparatorArray
    {
        get { return pathSeparatorArray; }
    }

    public static string PathSeparatorString
    {
        get { return pathSeparatorString; }
    }

   

}
 

0
freedo5
1/22/2008 3:15:41 AM
asp.net.navigation-controls 13714 articles. 0 followers. Follow

3 Replies
1249 Views

Similar Articles

[PageSpeed] 6

Thankyou! Exactly what I was looking for! I've been struggling with this problem 3 days and then I found this. Converted it to vb.net and did some small changes and now it works great.

Big Smile

0
redblueberry
10/9/2008 10:34:09 AM

 

Can you post your conversion and changes? I'm trying to do the same thing, and there's no use reinventing the wheel. Thanks
0
trumanBurbank
11/12/2008 10:39:36 PM

when i click the leaf node ie report it is not getting opened..iam getting error .Iam running on local environment and reports are on server.Some reports are parameterized and some are not....Could you please tell me how to solve  this issue for both

 

"

HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

Requested URL: /SSRSTreeView/ReportViewer/ReportViewer.aspx


Version Information: Microsoft .NET Framework Version:2.0.50727.1433; ASP.NET Version:2.0.50727.1433

0
hivenkat
2/23/2009 9:32:02 PM
Reply:

Similar Artilces:

System.Web.UI.WebControls.TreeView control in .Net Framework 2.0
Issue symptom: Storing serializable object data in tree nodes causes SelectedNodeChanged event freezing after a few levels to depth of the tree view. I'll send a sample code to show the details of the problem if somebody would like to help me out. Your help would be greatly appreciated. Thanks. Please send me the repro.ThanksJDThis posting is provided "AS IS" with no warranties, and confers no rights. We Are Hiring Is there any way I can send files to you as it seems no way to attach files?z2 Just sent you a private messge with my email addy.Thanks againJDThis posting is provided "AS ...

SQL Server Reporting Services for SQL SERVER 2000 AND Visual Studio.NET 2005 .NET 2.0
Hi, Which version of SQl Server Reporting Services will work with SQL SERVER 2000 in pararrel with ASP.NET 2.0 (.NET 2.0 framework)?  Thanks, Azam HighOnCodingWanna get high! Hi, Okay I got the answer. Yes, we can use the SQL SERVER 2005 Reporting Services with SQL SERVER 2000. HighOnCodingWanna get high! ...

.Net 2.0 Web application using Vb.net is unable to create object of another dll writen in C# .net 2.0
Hi, I habe created one ASP.net web application using Vb.net which is adding reference of dlls written in C# and .net 2.0. But whenever trying to create object of referencing dll, it is throwing error :Object reference does not set to an object. But, locally it is working fine,. In the server i have deployed the .aspx files and dll files in the bin. There were already an web.config in the server which is of .net 1.1. But checked it is retrieving value for that web.config correctly. Should i have to deply any other files and if not what can be the solution for this? Please help. Thanks, So...

.NET 2.0 Reporting Module using SQL Server Reporting Services
Hello Everyone,I have created a generic module using ASP.NET 2.0, MS SQL Server 2005 and SQL Server 2005 Reporting Services. This module is intended to provide a generic user interface for selecting and generating reports. You can configure its respective table for your fixed or flexible parameters for each report. It also supports end user access level security for each report and report group which is generally required for any basic reporting module.You can view reports in two different styles:-- Drop down--Tree View And You can view your report in 3 supported formats.  This is an in...

.Net 2 web app and Reporting Services (both SQL 2000 and SQL 2005)... Can it be done?
My setup:.Net 2 web app running in [localhost] with AJAX extensions.  2 virtual web folders Reports and ReportServer for Reporting Services in SQL 2000.  I understand that RS (Reporting Services) for SQL 2000 only runs in .Net Framework 1.1, so I have set both Reports and ReportServer to run in a different application pool [ASP.NET 1.1] and set their .net Framework to 1.1.  But when I try to load a report through our app or try to load the Reports folder it reports and error in the web.config of our web app in localhost.  The error in the web.config is something specific ...

How to design SQL Server 2005 Reporting Services Reports in VS.NET 2005 web applications
Hi,   Can we design SQL Server 2005 Reporting Services Reports in VS.NET 2005 web applications. If so how they can be designed. Plz help me if any one know the solution. Thanx in advance, Vidya     Are you asking if you can use VS.Net 2005 to design reports, yes, both client and server reports are built using VS.Net. If you are asking if you can use a web application to build a report, well yes you could, but you would have you design it.  All sql server reports are is an xml file, so if you can build a front end that will generate the xml in the proper ...

no Expandable property for System.Web.UI.WebControls.TreeNode in .NET Framework 2.0?
Is there any kind of Expandable property for System.Web.UI.WebControls.TreeNode in .NET Framework 2.0? Any help is greatly appreciated. Not that I know of - but you can check node.PopulateOnDemandandnode.ChildNodes.CountIf POD is true OR Count >0 that should tell you what you need to know, you could extend node and add the expandable prop...I'll enter a OM suggestion bug for adding this to the next version.JDThis posting is provided "AS IS" with no warranties, and confers no rights. We Are Hiring...

no ExpandedImageUrl property for System.Web.UI.WebControls.TreeNode in .NET Framework 2.0?
Is there any kind of ExpandedImageUrl property for System.Web.UI.WebControls.TreeNode in .NET Framework 2.0? Any help is greatly appreciated. Not on the node object directly - but on the TreeView object itself you will find the property.This posting is provided "AS IS" with no warranties, and confers no rights. We Are Hiring...

useing System.Net.Mail in Net 2.0
Useing C# and VWD enviroment with the Test server in VWD. Code for Mail does not work in 2.0, get an error like this:  System.Net.Mail.SmtpException was unhandled by user code Message="Failure sending mail." Source="System" line 42 which is the smtp.Send(email) line. Code for the old way in 1.1 works just fine, here is what I use (email is bogus for this) The commented line are for Net 1.1 which works. Any ideas what I need to do? Thanks using System.Net.Mail;//using System.Web.Mail; protected void Button1_Click(object sender, EventArgs e)  {  ERMessag...

Differences between .net 1, .net 1.1, .net 2.0 and .net 3.0 #2
Hi, This seems to be a common question, but i havent got an answer yet:(Can, any one please explain me the differences between these versions.If you keep your feet firmly on the ground, you'll have trouble putting on your pants! There are too many differences for one email - - from 1.0 to 1.1 (not a whole lot of real change, other than fixes, at least compared to 1.1 to 2.0) With 2.0, there were many new declarative controls, with many new ideas added in With 3.0, it's a superset of 2.0 - instead of replacing the installation completely, it just 'added on' new functionality - I would...

Access .Net 2.0 Application from .Net 2.0 Web Site
I need to populate a specific form in a .Net desktop application from a .net web application.  Is there an easy way to go about this? Hi, Based on my understanding, you want to start an executable application from your ASP.NET websit, right? We can invoke Process.Start method (http://msdn.microsoft.com/en-us/library/system.diagnostics.process.start.aspx) to launch an executable application from ASP.NET application. Note: Please keep in mind, the ASP.NET application is running on the server, so it will start the executable application that exists in the server.   I look...

Could not load type System.Web.UI.WebControls.TreeView from assembly System.Web, Version=1.0.5000.0,
  Server Error in '/Demo1' Application. Parser Error Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. Parser Error Message: Could not load type System.Web.UI.WebControls.TreeView from assembly System.Web, Version=1.0.5000.0, Culture=neutral, Source Error: Line 10: <form> Line 11: Line 12: <asp:TreeView runat="server"> Line 13: <Nodes> Line 14: <asp:TreeNode Text="Employees"">Sourc...

How to get new web app to use .NET 2.0 on Win2K server using .NET 1.1 as default framework?
I have .net framework1.1 and 2.0 on our server running win2K. i have existing applications that uses asp.net 1.1, i also have a new app that use ASP.net 2.0.  how can i set my new .NET 2.0 app to point to asp.net 2.0 without messing up my existing .NET 1.1 apps? To specify the ASP .Net version fro a web application, do the followingIn IIS Manager select the web application -> Properties -> ASP.Net TabSelect  ASP.Net version you want to use for the applicationRegards,PrashantDont forget to click "Mark as Answer" on the post that helped you. But I am running Win2K...

HTTP protocol violation error using .NET 2.0 web services through Squid-2.5 proxy
Hello,A client of ours using the Squid proxy server (version 2.5.STABLE6-3.4E.12.1) on Red Hat Enterprise Linux 4 is experiencing a problem when running our .NET 2.0 client application, which communicates with a .NET 2.0 web service on our server.When our client application sends an HTTP 1.1 request through the Squid proxy to our server, it receives the error:"The server committed a protocol violation. Section=ResponseStatusLine"Other clients not using Squid are not experiencing this problem.Researching this, we've found a few posts that report similar problems using .NET 2.0 w...

Web resources about - Using .Net 2.0 and System.Web.UI.WebControls.Treeview with SQL Reporting Services 2005 for navigation and display. - asp.net.navigation-controls

Request a demo - Connexus Support
Business Internet ASL SYMMETRIC ETHERNET HYBRID Hosting DOMAIN + WEB CO-LOCATION FACILITIES MAIL Networks MPLS / VPN SSL / VPN Web Tool WEBCONTROL ...

SEO Blog - Search Engine Optimisation / Search Engine Marketing & general IT blog
Read the AKA Marketing search engine optimisation blog for posts about the latest organic search engine optimisation and search engine marketing ...

ALSEDI Group. Excellent Software. Excellent Usability.
ALSEDI Group Portal. High quality Surveillance, Privacy Protection and Desktop Enhancement software.

Case insensitive compare on string in ASP.NET - Coders Grid
using System ; using System.Collections.Generic ; using System.Linq ; using System.Web ; using System.Web.UI ; using System.Web.UI.WebControls ...

advsearch
Hong Kong 繁体中文 / English China 简体中文 United States English Canada Francais / English Central-South America & Caribbean Region English / Espanol ...

Copyright Information - Media Temple
The (mt) Media Temple (mediatemple.net) web site, including all text, HTML, scripts, and images are copyright 1998-2014. All rights reserved. ...

New Microsoft DevRadio Episode: World of Warcraft API Starter Kit for Windows Phone
This is the blog of Dave Isbitski. A Technology Evangelist for Microsoft based out of Philadelphia, PA USA. He is currently focused on helping ...

Adventures in Worstpracticeville
This morning, I wrote ~4500 lines of code in about two minutes. Skeptical? I thought you would be, so here's the curious tale of how I deviated ...

ConditionalRequiredTextValidator Control
The ConditionalRequiredTextValidator control allows you to specify a CheckBox, RadioButton, CheckBoxList, RadioButtonList, DropDownList, or ListBox ...

IT Managed Service Providers with Datacenters in India - Netmagic
As a leading Managed service provider with datacenters in India, Netmagic solutions, fulfills your entire IT infrastructure requirements: from ...

Resources last updated: 12/26/2015 5:51:52 AM