• [ASP.NET] : HierarchicalObjectDataSource


    前言 :

    ASP.NET 3.5提供了,网页上常使用到的树状选单TreeView。
    可是TreeView的数据系结,并没有支持ObjectDataSource。
    这篇文章分享如何实做ObjectDataSource,来支持TreeView的数据系结功能。

    分析设计 :

    TreeView的DataSource只支持实做IHierarchicalDataSource接口的对象。
    IHierarchicalDataSource这个看似简单的接口,里面却包含了很多子界面。
    将整个IHierarchicalDataSource拆解开来,并且经过分析设计之后的对象图如下 :

    每个对象的职责就不赘述了,大多为符合IHierarchicalDataSource所规范的功能而实做。
    整个设计比较特别的只有IHierarchicalObjectDataFactory接口。
    这个接口其实是多余的,只是为了不让HierarchicalObjectDataEnumerable及HierarchicalObjectData有循环相依。

    执行结果 :

    使用范例 :

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CLK.Web.UI.WebApplication._Default" %> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml" > 
    <head id="Head1" runat="server"> 
    <title></title> 
    </head> 
    <body> 
    <form id="form1" runat="server"> 
    <div> 
    <asp:TreeView ID="TreeView1" runat="server"> 
    <DataBindings> 
    <asp:TreeNodeBinding TextField="Name" ValueField="Id" /> 
    </DataBindings> 
    </asp:TreeView> 
    </div> 
    </form> 
    </body> 
    </html>
    namespace CLK.Web.UI.WebApplication
    {
        public partial class _Default : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (this.IsPostBack == false)
                {
                    List<IHierarchicalObject> demoDataList = new List<IHierarchicalObject>();
                    demoDataList.Add(new DemoData(null, "AAA", "Id_AAA", "Name_AAA"));
                    demoDataList.Add(new DemoData(null, "BBB", "Id_BBB", "Name_BBB"));
                    demoDataList.Add(new DemoData(null, "CCC", "Id_CCC", "Name_CCC"));
                    demoDataList.Add(new DemoData("BBB", "DDD", "Id_DDD", "Name_DDD"));
                    demoDataList.Add(new DemoData("DDD", "EEE", "Id_EEE", "Name_EEE"));
                    demoDataList.Add(new DemoData(null, "FFF", "Id_FFF", "Name_FFF"));
    
                    HierarchicalObjectDataSource dataSource = new HierarchicalObjectDataSource(demoDataList);
                    TreeView1.DataSource = dataSource;
                    TreeView1.DataBind();
                }
            }
        }
    
        public class DemoData : IHierarchicalObject
        {
            // Properties 
            private readonly string _parentPath;
    
            private readonly string _path;
    
            private readonly string _id;
    
            private readonly string _name;
    
    
            // Construction 
            public DemoData(string parentPath, string path, string id, string name)
            {
                #region Require
    
                if (path == null) throw new ArgumentNullException();
                if (string.IsNullOrEmpty(id) == true) throw new ArgumentNullException();
                if (string.IsNullOrEmpty(name) == true) throw new ArgumentNullException();
    
                #endregion
                _parentPath = parentPath;
                _path = path;
                _id = id;
                _name = name;
            }
    
    
            // Member 
            public string ParentPath
            {
                get { return _parentPath; }
            }
    
            public string Path
            {
                get { return _path; }
            }
    
            public string Id
            {
                get { return _id; }
            }
    
            public string Name
            {
                get { return _name; }
            }
        }
    }

    实作 :

    namespace CLK.Web.UI
    {
        public class HierarchicalObjectDataSource : IHierarchicalDataSource
        {
            // Properties 
            private readonly IEnumerable<IHierarchicalObject> _objectEnumerable;
    
    
            // Construction 
            public HierarchicalObjectDataSource(IEnumerable<IHierarchicalObject> objectEnumerable)
            {
                #region Require
    
                if (objectEnumerable == null) throw new ArgumentNullException();
    
                #endregion
                _objectEnumerable = objectEnumerable;
            }
    
    
            // Member 
            public HierarchicalDataSourceView GetHierarchicalView(string viewPath)
            {
                return new HierarchicalObjectDataSourceView(_objectEnumerable, viewPath);
            }
    
    
            // Event 
            public event EventHandler DataSourceChanged;
            protected void OnDataSourceChanged(object sender, EventArgs e)
            {
                if (this.DataSourceChanged != null)
                {
                    this.DataSourceChanged(sender, e);
                }
            }
        }
    
        public class HierarchicalObjectDataSourceView : HierarchicalDataSourceView
        {
            // Properties 
            private readonly IEnumerable<IHierarchicalObject> _objectEnumerable;
    
            private readonly IHierarchicalObject _currentObject;
    
            private readonly IHierarchicalObjectDataFactory _objectFactory;
    
    
            // Construction 
            public HierarchicalObjectDataSourceView(IEnumerable<IHierarchicalObject> objectEnumerable, string path)
            {
                #region Require
    
                if (objectEnumerable == null) throw new ArgumentNullException();
                if (path == null) throw new ArgumentNullException();
    
                #endregion
                _objectFactory = new HierarchicalObjectDataFactory();
    
                _objectEnumerable = objectEnumerable;
    
                _currentObject = null;
                foreach (IHierarchicalObject currentObject in _objectEnumerable)
                {
                    if (currentObject.Path == path)
                    {
                        _currentObject = currentObject;
                        break;
                    }
                }
            }
    
    
            // Member 
            public override IHierarchicalEnumerable Select()
            {
                return _objectFactory.CreateHierarchicalEnumerable(_objectEnumerable, _currentObject);
            }
        }
    
        public class HierarchicalObjectDataFactory : IHierarchicalObjectDataFactory
        {
            // Member 
            public IHierarchicalEnumerable CreateHierarchicalEnumerable(IEnumerable<IHierarchicalObject> objectEnumerable, IHierarchicalObject currentObject)
            {
                return new HierarchicalObjectDataEnumerable(objectEnumerable, currentObject, this);
            }
    
            public IHierarchyData CreateHierarchyData(IEnumerable<IHierarchicalObject> objectEnumerable, IHierarchicalObject currentObject)
            {
                return new HierarchicalObjectData(objectEnumerable, currentObject, this);
            }
        }
    
        public interface IHierarchicalObjectDataFactory
        {
            IHierarchicalEnumerable CreateHierarchicalEnumerable(IEnumerable<IHierarchicalObject> objectEnumerable, IHierarchicalObject currentObject);
    
            IHierarchyData CreateHierarchyData(IEnumerable<IHierarchicalObject> objectEnumerable, IHierarchicalObject currentObject);
        }
    
        public class HierarchicalObjectDataEnumerable : IHierarchicalEnumerable
        {
            // Properties 
            private readonly IEnumerable<IHierarchicalObject> _objectEnumerable;
    
            private readonly IHierarchicalObject _currentObject;
    
            private readonly IHierarchicalObjectDataFactory _objectFactory;
    
    
            // Construction 
            public HierarchicalObjectDataEnumerable(IEnumerable<IHierarchicalObject> objectEnumerable, IHierarchicalObject currentObject, IHierarchicalObjectDataFactory objectFactory)
            {
                #region Require
    
                if (objectEnumerable == null) throw new ArgumentNullException();
                //if (currentObject == null) throw new ArgumentNullException(); 
                if (objectFactory == null) throw new ArgumentNullException();
    
                #endregion
                _objectEnumerable = objectEnumerable;
                _currentObject = currentObject;
                _objectFactory = objectFactory;
            }
    
    
            // Member 
            public IHierarchyData GetHierarchyData(object enumeratedItem)
            {
                #region Require
    
                if (enumeratedItem == null) throw new ArgumentNullException();
    
                #endregion
                if (enumeratedItem is IHierarchicalObject)
                {
                    return _objectFactory.CreateHierarchyData(_objectEnumerable, enumeratedItem as IHierarchicalObject);
                }
                return null;
            }
    
            public System.Collections.IEnumerator GetEnumerator()
            {
                return new HierarchicalObjectDataEnumerator(_objectEnumerable.GetEnumerator(), _currentObject);
            }
        }
    
        public class HierarchicalObjectDataEnumerator : IEnumerator<IHierarchicalObject>
        {
            // Properties 
            private readonly IEnumerator<IHierarchicalObject> _objectEnumerator;
    
            private readonly IHierarchicalObject _currentObject;
    
            private IHierarchicalObject _currentChildrenObject = null;
    
    
            // Construction 
            public HierarchicalObjectDataEnumerator(IEnumerator<IHierarchicalObject> objectEnumerator, IHierarchicalObject currentObject)
            {
                #region Require
    
                if (objectEnumerator == null) throw new ArgumentNullException();
                //if (currentObject == null) throw new ArgumentNullException(); 
    
                #endregion
                _objectEnumerator = objectEnumerator;
                _currentObject = currentObject;
            }
    
            public void Dispose()
            {
                _objectEnumerator.Dispose();
            }
    
    
            // Member 
            public IHierarchicalObject Current
            {
                get
                {
                    return _currentChildrenObject;
                }
            }
    
            object System.Collections.IEnumerator.Current
            {
                get
                {
                    return this.Current;
                }
            }
    
            public bool MoveNext()
            {
                while (_objectEnumerator.MoveNext() == true)
                {
                    if (_currentObject != null)
                    {
                        if (_objectEnumerator.Current.ParentPath == _currentObject.Path)
                        {
                            _currentChildrenObject = _objectEnumerator.Current;
                            return true;
                        }
                    }
                    else
                    {
                        if (_objectEnumerator.Current.ParentPath == null)
                        {
                            _currentChildrenObject = _objectEnumerator.Current;
                            return true;
                        }
                    }
                }
    
                _currentChildrenObject = null;
                return false;
            }
    
            public void Reset()
            {
                _objectEnumerator.Reset();
                _currentChildrenObject = null;
            }
        }
    
        public class HierarchicalObjectData : IHierarchyData
        {
            // Properties 
            private readonly IEnumerable<IHierarchicalObject> _objectEnumerable;
    
            private readonly IHierarchicalObject _currentObject;
    
            private readonly IHierarchicalObjectDataFactory _objectFactory;
    
    
            // Construction 
            public HierarchicalObjectData(IEnumerable<IHierarchicalObject> objectEnumerable, IHierarchicalObject currentObject, IHierarchicalObjectDataFactory objectFactory)
            {
                #region Require
    
                if (objectEnumerable == null) throw new ArgumentNullException();
                if (currentObject == null) throw new ArgumentNullException();
                if (objectFactory == null) throw new ArgumentNullException();
    
                #endregion
                _objectEnumerable = objectEnumerable;
                _currentObject = currentObject;
                _objectFactory = objectFactory;
            }
    
    
            // Member 
            public IHierarchicalEnumerable GetChildren()
            {
                return _objectFactory.CreateHierarchicalEnumerable(_objectEnumerable, _currentObject);
            }
    
            public IHierarchyData GetParent()
            {
                if (_currentObject.ParentPath != null)
                {
                    foreach (IHierarchicalObject parentObject in _objectEnumerable)
                    {
                        if (parentObject.Path == _currentObject.ParentPath)
                        {
                            return _objectFactory.CreateHierarchyData(_objectEnumerable, parentObject);
                        }
                    }
                }
                return null;
            }
    
            public bool HasChildren
            {
                get
                {
                    foreach (object childrenObject in this.GetChildren())
                    {
                        return true;
                    }
                    return false;
                }
            }
    
            public object Item
            {
                get { return _objectFactory.CreateHierarchyData(_objectEnumerable, _currentObject); }
            }
    
            public string Path
            {
                get { return _currentObject.Path; }
            }
    
            public string Type
            {
                get { return _currentObject.GetType().ToString(); }
            }
        }
    
        public interface IHierarchicalObject
        {
            string Path { get; }
    
            string ParentPath { get; }
        }
    }
  • 相关阅读:
    React 高阶组件
    Facebook Graph API 接口请求
    (转载)HTML:模拟链接被按下,在新标签页打开页面,不使用window.open(可能被拦截)
    php file_put_contents() 写入回车
    mysql 慢查询开启
    FB接口之 js调用支付窗口
    8 个必备的PHP功能开发
    linux 负载 待读
    大话团队管理。
    API编排
  • 原文地址:https://www.cnblogs.com/clark159/p/2205036.html
Copyright © 2020-2023  润新知