System.Web.UI


.NET Framework Class Library
HierarchicalDataSourceControl Class

Note: This class is new in the .NET Framework version 2.0.

Provides a base class for data source controls that represent hierarchical data.

Namespace: System.Web.UI
Assembly: System.Web (in system.web.dll)

Syntax

Visual Basic (Declaration)
<BindableAttribute(False)> _
Public MustInherit Class HierarchicalDataSourceControl
    Inherits Control
    Implements IHierarchicalDataSource
Visual Basic (Usage)
Dim instance As HierarchicalDataSourceControl
C#
[BindableAttribute(false)] 
public abstract class HierarchicalDataSourceControl : Control, IHierarchicalDataSource
C++
[BindableAttribute(false)] 
public ref class HierarchicalDataSourceControl abstract : public Control, IHierarchicalDataSource
J#
/** @attribute BindableAttribute(false) */ 
public abstract class HierarchicalDataSourceControl extends Control implements IHierarchicalDataSource
JScript
BindableAttribute(false) 
public abstract class HierarchicalDataSourceControl extends Control implements IHierarchicalDataSource
Remarks

ASP.NET supports a controls data-binding architecture that enables Web server controls to bind to data and present it in a consistent fashion. Web server controls that bind to data are called data-bound controls, and the classes that facilitate binding are called data source controls. Data source controls can represent any data source: a file, a stream, a relational database, a business object, and so on. Data source controls present data in a consistent way to data-bound controls, regardless of the source or format of the underlying data.

Data source controls that represent hierarchical data derive from the HierarchicalDataSourceControl class, while data source controls that represent lists or tables of data derive from the DataSourceControl class. The HierarchicalDataSourceControl class is the base implementation of the IHierarchicalDataSource interface, which defines a single method to retrieve hierarchical data source view objects associated with the data source control, GetHierarchicalView.

You can think of a data source control as the combination of the HierarchicalDataSourceControl object and its associated views on the underlying data, called data source view objects. While data source controls that represent tabular data are typically associated with only one named view, the HierarchicalDataSourceControl class supports a data source view for each level of hierarchical data that the data source control represents. The level of hierarchical data is identified by a unique hierarchical path, passed to the GetHierarchicalView method in the viewPath parameter. Each HierarchicalDataSourceView object defines the capabilities of a data source control for the hierarchical level represented, and performs operations such as insert, update, delete, and sort.

Web server controls that derive from the HierarchicalDataBoundControl class, such as TreeView, use hierarchical data source controls to bind to hierarchical data.

Data source controls are implemented as controls to enable declarative persistence and to optionally permit participation in state management. Data source controls have no visual rendering, and therefore do not support themes.

Example

The following code example demonstrates how to extend the abstract HierarchicalDataSourceControl class and the HierarchicalDataSourceView class, and implement the IHierarchicalEnumerable and IHierarchyData interfaces to create a hierarchical data source control that retrieves file system information. The FileSystemDataSource control enables Web server controls to bind to FileSystemInfo objects and display basic file system information. The FileSystemDataSource class in the example provides the implementation of the GetHierarchicalView method, which retrieves a FileSystemDataSourceView object. The FileSystemDataSourceView object retrieves the data from the underlying data storage, in this case the file system information on the Web server. For security purposes, file system information is displayed only if the data source control is being used in a localhost, authenticated scenario, and only starts with the virtual directory that the Web Forms page using the data source control resides in. Finally, two classes that implement IHierarchicalEnumerable and IHierarchyData are provided to wrap the FileSystemInfo objects that FileSystemDataSource uses.

Visual Basic
Imports System
Imports System.Collections
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace Samples.AspNet

<AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal)> _
Public Class FileSystemDataSource
   Inherits HierarchicalDataSourceControl

   Public Sub New()
   End Sub 'New
   ' Return a strongly typed view for the current data source control.
   Private view As FileSystemDataSourceView = Nothing

   Protected Overrides Function GetHierarchicalView(viewPath As String) As HierarchicalDataSourceView
      If view Is Nothing Then
         view = New FileSystemDataSourceView(viewPath)
      End If
      Return view
   End Function 'GetHierarchicalView

End Class 'FileSystemDataSource
' The FileSystemDataSourceView class encapsulates the
' capabilities of the FileSystemDataSource data source control.

Public Class FileSystemDataSourceView
   Inherits HierarchicalDataSourceView

   Private _viewPath As String

   Public Sub New(viewPath As String)
       ' This implementation of HierarchicalDataSourceView does not
       ' use the viewPath parameter but other implementations
       ' could make use of it for retrieving values.
       _viewPath = viewPath
   End Sub 'New


   ' Starting with the rootNode, recursively build a list of
   ' FileSystemInfo nodes, create FileSystemHierarchyData
   ' objects, add them all to the FileSystemHierarchicalEnumerable,
   ' and return the list.
   Public Overrides Function [Select]() As IHierarchicalEnumerable
      Dim currentRequest As HttpRequest = HttpContext.Current.Request

      ' SECURITY: There are many security issues that can be raised
      ' SECURITY: by exposing the file system structure of a Web server
      ' SECURITY: to an anonymous user in a limited trust scenario such as
      ' SECURITY: a Web page served on an intranet or the Internet.
      ' SECURITY: For this reason, the FileSystemDataSource only
      ' SECURITY: shows data when the HttpRequest is received
      ' SECURITY: from a local Web server. In addition, the data source
      ' SECURITY: does not display data to anonymous users.
      If currentRequest.IsAuthenticated AndAlso(currentRequest.UserHostAddress = "127.0.0.1" OrElse currentRequest.UserHostAddress = "::1") Then

         ' The ApplicationPath returns a physical path in VB, so do not MapPath.
         Dim rootPath As String = currentRequest.MapPath(currentRequest.ApplicationPath)

         Dim rootDirectory As New DirectoryInfo(rootPath)

         Dim fshe As New FileSystemHierarchicalEnumerable()

         Dim fsi As FileSystemInfo
         For Each fsi In  rootDirectory.GetFileSystemInfos()
            fshe.Add(New FileSystemHierarchyData(fsi))
         Next fsi
         Return fshe
      Else
         Throw New NotSupportedException("The FileSystemDataSource only " + "presents data in an authenticated, localhost context.")
      End If
   End Function 'Select
End Class 'FileSystemDataSourceView
' A collection of FileSystemHierarchyData objects

Public Class FileSystemHierarchicalEnumerable
   Inherits ArrayList
   Implements IHierarchicalEnumerable

   Public Sub New()
   End Sub 'New


   Public Overridable Function GetHierarchyData(enumeratedItem As Object) As IHierarchyData _
    Implements IHierarchicalEnumerable.GetHierarchyData
      Return CType(enumeratedItem, IHierarchyData)
   End Function 'GetHierarchyData

End Class 'FileSystemHierarchicalEnumerable


Public Class FileSystemHierarchyData
   Implements IHierarchyData

   Public Sub New(obj As FileSystemInfo)
      fileSystemObject = obj
   End Sub 'New

   Private fileSystemObject As FileSystemInfo = Nothing

   Public Overrides Function ToString() As String
      Return fileSystemObject.Name
   End Function 'ToString

   ' IHierarchyData implementation.
   Public Overridable ReadOnly Property HasChildren() As Boolean _
    Implements IHierarchyData.HasChildren
      Get
         If GetType(DirectoryInfo) Is fileSystemObject.GetType() Then
            Dim temp As DirectoryInfo = CType(fileSystemObject, DirectoryInfo)
            Return temp.GetFileSystemInfos().Length > 0
         Else
            Return False
         End If
      End Get
   ' DirectoryInfo returns the OriginalPath, while FileInfo returns
   ' a fully qualified path.

   Public Overridable ReadOnly Property Path() As String _
    Implements IHierarchyData.Path
      Get
         Return fileSystemObject.ToString()
      End Get
   End Property

   Public Overridable ReadOnly Property Item() As Object _
    Implements IHierarchyData.Item
      Get
         Return fileSystemObject
      End Get
   End Property

   Public Overridable ReadOnly Property Type() As String _
    Implements IHierarchyData.Type
      Get
         Return "FileSystemData"
      End Get
   End Property

   Public Overridable Function GetChildren() As IHierarchicalEnumerable _
    Implements IHierarchyData.GetChildren
      Dim children As New FileSystemHierarchicalEnumerable()

      If GetType(DirectoryInfo) Is fileSystemObject.GetType() Then
         Dim temp As DirectoryInfo = CType(fileSystemObject, DirectoryInfo)
         Dim fsi As FileSystemInfo
         For Each fsi In  temp.GetFileSystemInfos()
            children.Add(New FileSystemHierarchyData(fsi))
         Next fsi
      End If
      Return children
   End Function 'GetChildren


   Public Overridable Function GetParent() As IHierarchyData _
    Implements IHierarchyData.GetParent
      Dim parentContainer As New FileSystemHierarchicalEnumerable()

      If GetType(DirectoryInfo) Is fileSystemObject.GetType() Then
         Dim temp As DirectoryInfo = CType(fileSystemObject, DirectoryInfo)
         Return New FileSystemHierarchyData(temp.Parent)
      ElseIf GetType(FileInfo) Is fileSystemObject.GetType() Then
         Dim temp As FileInfo = CType(fileSystemObject, FileInfo)
         Return New FileSystemHierarchyData(temp.Directory)
      End If
      ' If FileSystemObj is any other kind of FileSystemInfo, ignore it.
      Return Nothing
   End Function 'GetParent
End Class 'FileSystemHierarchyData
End Namespace
C#
using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Minimal)]
public class FileSystemDataSource : HierarchicalDataSourceControl, IHierarchicalDataSource
{
    public FileSystemDataSource() : base() {}

    // Return a strongly typed view for the current data source control.
    private FileSystemDataSourceView view = null;
    protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath) {
        if (null == view) {
            view = new FileSystemDataSourceView(viewPath);
        }
        return view;
    }

    // The FileSystemDataSource can be used declaratively. To enable
    // declarative use, override the default implementation of
    // CreateControlCollection to return a ControlCollection that
    // you can add to.
    protected override ControlCollection CreateControlCollection() {
        return new ControlCollection(this);
    }
}
// The FileSystemDataSourceView class encapsulates the
// capabilities of the FileSystemDataSource data source control.
public class FileSystemDataSourceView : HierarchicalDataSourceView
{
private string _viewPath;

    public FileSystemDataSourceView(string viewPath)
    {
        // This implementation of HierarchicalDataSourceView does not
        // use the viewPath parameter but other implementations
        // could make use of it for retrieving values.
        _viewPath = viewPath;
    }

    // Starting with the rootNode, recursively build a list of
    // FileSystemInfo nodes, create FileSystemHierarchyData
    // objects, add them all to the FileSystemHierarchicalEnumerable,
    // and return the list.
    public override IHierarchicalEnumerable Select() {
        HttpRequest currentRequest = HttpContext.Current.Request;

        // SECURITY: There are many security issues that can be raised
        // SECURITY: by exposing the file system structure of a Web server
        // SECURITY: to an anonymous user in a limited trust scenario such as
        // SECURITY: a Web page served on an intranet or the Internet.
        // SECURITY: For this reason, the FileSystemDataSource only
        // SECURITY: shows data when the HttpRequest is received
        // SECURITY: from a local Web server. In addition, the data source
        // SECURITY: does not display data to anonymous users.
        if ( currentRequest.IsAuthenticated &&
            (currentRequest.UserHostAddress == "127.0.0.1" ||
             currentRequest.UserHostAddress == "::1"))
        {
            string rootPath = currentRequest.MapPath (currentRequest.ApplicationPath);

            DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);

            FileSystemHierarchicalEnumerable fshe = new FileSystemHierarchicalEnumerable();

            foreach (FileSystemInfo fsi in rootDirectory.GetFileSystemInfos()) {
                fshe.Add(new FileSystemHierarchyData(fsi));
            }
            return fshe;
        }
        else {
            throw new NotSupportedException("The FileSystemDataSource only " + "presents data in an authenticated, localhost context.");
        }
    }
}
// A collection of FileSystemHierarchyData objects
public class FileSystemHierarchicalEnumerable : ArrayList, IHierarchicalEnumerable
{
    public FileSystemHierarchicalEnumerable () : base (){
    }

    public IHierarchyData GetHierarchyData(object enumeratedItem) {
        return enumeratedItem as IHierarchyData;
    }
}

public class FileSystemHierarchyData : IHierarchyData
{
    public FileSystemHierarchyData (FileSystemInfo obj) {
        fileSystemObject = obj;
    }

    private FileSystemInfo fileSystemObject = null;

    public override string ToString() {
        return fileSystemObject.Name;
    }
    // IHierarchyData implementation.
    public bool HasChildren {
        get {
            if (typeof(DirectoryInfo) ==  fileSystemObject.GetType()   ) {
                DirectoryInfo temp = (DirectoryInfo) fileSystemObject;
                return (temp.GetFileSystemInfos().Length > 0);
            }
            else return false;
        }
    }
    // DirectoryInfo returns the OriginalPath, while FileInfo returns
    // a fully qualified path.
    public string Path {
        get {
            return fileSystemObject.ToString();
        }
    }
    public object Item {
        get {
            return fileSystemObject;
        }
    }
    public string Type {
        get {
            return "FileSystemData";
        }
    }
    public IHierarchicalEnumerable GetChildren() {
        FileSystemHierarchicalEnumerable children =
            new FileSystemHierarchicalEnumerable();

        if (typeof(DirectoryInfo) == fileSystemObject.GetType()) {
            DirectoryInfo temp = (DirectoryInfo)fileSystemObject;
            foreach (FileSystemInfo fsi in temp.GetFileSystemInfos()) {
                children.Add(new FileSystemHierarchyData(fsi));
            }
        }
        return children;
    }

    public IHierarchyData GetParent()
    {
        FileSystemHierarchicalEnumerable parentContainer =
            new FileSystemHierarchicalEnumerable();

        if (typeof(DirectoryInfo) == fileSystemObject.GetType())
        {
            DirectoryInfo temp = (DirectoryInfo)fileSystemObject;
            return new FileSystemHierarchyData(temp.Parent);
        }
        else if (typeof(FileInfo) == fileSystemObject.GetType())
        {
            FileInfo temp = (FileInfo)fileSystemObject;
            return new FileSystemHierarchyData(temp.Directory);
        }
        // If FileSystemObj is any other kind of FileSystemInfo, ignore it.
        return null;
    }
}

The following code example demonstrates how to declaratively bind a TreeView control to file system data using the FileSystemDataSource example.

Visual Basic
Imports System
Imports System.Collections
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace Samples.AspNet.VB

<AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal)> _
Public Class FileSystemDataSource
   Inherits HierarchicalDataSourceControl

   Public Sub New()
   End Sub 'New
   ' Return a strongly typed view for the current data source control.
   Private view As FileSystemDataSourceView = Nothing

   Protected Overrides Function GetHierarchicalView(viewPath As String) As HierarchicalDataSourceView
      If view Is Nothing Then
         view = New FileSystemDataSourceView(viewPath)
      End If
      Return view
   End Function 'GetHierarchicalView

End Class 'FileSystemDataSource
C#
using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Minimal)]
public class FileSystemDataSource : HierarchicalDataSourceControl, IHierarchicalDataSource
{
    public FileSystemDataSource() : base() {}

    // Return a strongly typed view for the current data source control.
    private FileSystemDataSourceView view = null;
    protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath) {
        if (null == view) {
            view = new FileSystemDataSourceView(viewPath);
        }
        return view;
    }

    // The FileSystemDataSource can be used declaratively. To enable
    // declarative use, override the default implementation of
    // CreateControlCollection to return a ControlCollection that
    // you can add to.
    protected override ControlCollection CreateControlCollection() {
        return new ControlCollection(this);
    }
}
.NET Framework Security

Inheritance Hierarchy

System.Object
   System.Web.UI.Control
    System.Web.UI.HierarchicalDataSourceControl
       System.Web.UI.WebControls.SiteMapDataSource
       System.Web.UI.WebControls.XmlDataSource
Thread Safety

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Platforms

Windows 98, Windows 2000 SP4, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see System Requirements.

Version Information

.NET Framework

Supported in: 2.0
See Also

Tags :


Community Content

bgard6977
This code doesn't even compile.
The code doesn't even compile. There is no "End Property" to HasChildren() in the VB code. Even if you add the "End Property", it just loops indefinitely, and generates a stack overflow. Great job guys.
Tags :

xanTh
This example is unusable
I written code similar this example (in this example no end bracers } in c#), and I have "stack overflow error" when binded datasoure to TreeView. Then I add "}" in your code for compile it and also binded this datasource to TreeView control and I have same Stack Overflow Exception. "Thanks", you killed my 6 hours.
Tags :

Sebastian Rogers
But is simple to fix

The issue is the Select method in particular the line

DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);

Thus each time the select method is run it returns the root directory

This can be fixed by using the _viewPath however by default this is return the folder's ToString() and not the FullName so its not a step by step path but just the last step in the path.

We fix this by editing the FileSystemHierarchyData's Path method

  public string Path
{
get
{
return fileSystemObject.FullName;
}
}

Now we can alter the FileSystemDataSourceView's Select method to use either the rootPath or the _viewPath depending on if we are already part of the way down the tree

    DirectoryInfo rootDirectory = new DirectoryInfo(_viewPath == string.Empty ? rootPath : _viewPath);

Then the recursion works.

Try setting the TreeView's ExpandDepth to 0 and stepping through the code to see what is happening as each branch is expanded.

Sebastian Rogers

Tags :

sixeyes
Further fix
Sebastian,

Your fix was most helpful. Once I could actually run the sample I was able to understand how to fix another bug with the sample.

You had to set ExpandDepth to 0 but this isn't necessary with a further change.

I made _viewPath settable outside of the constructor. This is necessary because the code in FileSystemDataSource must set it.

protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath)
{
if (null == view)
view = new FileSystemDataSourceView(viewPath);
else
view.ViewPath = viewPath;

return view;
}

I've added the else clause. Without this test, GetHierarchicalView will only work correctly when a view is created. For each postback view will be null so ExpandDepth = 0 allows this to work.

If you want ExpandDepth > 0 you need to make sure the view has the correct view path (hence why _viewPath must be settable by an external object)


I hope that saves other people some time.

Thanks again Sebastian, you really saved me some time.

Iain
Tags :

Page view tracker