[ASP.NET] HierarchicalObjectDataSource Part2

[ASP.NET] : HierarchicalObjectDataSource Part2


前言 :

之前發布了一篇[ASP.NET] : HierarchicalObjectDataSource
本篇是它的Part2,內容沒有新的東西。
只是把上一篇發表的物件,套用一些Design Patterns。
來達到異種資料的資料繫結。


一般寫ASP.NET使用TreeView,大多使用XmlDataSource或是SiteMapDataSource做資料繫結,不然就是依照資料去程式動態建立TreeNode。
HierarchicalObjectDataSource 封裝了階層式資料繫結的複雜運算,讓TreeView的資料繫結開發變的可行。
依照這兩篇HierarchicalObjectDataSource的文章思路繼續開發下去,相信會有更多的延伸應用。


執行結果 :

下圖為底下所有範例程式碼執行的結果。上半部表格將資料內容條列 ,下半部樹狀選單將資料內容顯示為樹狀。
image


樹狀物件資料繫結 :

樹狀物件資料繫結,主要是使用Iterator這個Pattern來將樹狀資料做扁平化處理。


namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.IsPostBack == false)
            {
                IEnumerable<DemoData> demoDataEnumerable = this.CreateDemoDataEnumerable();

                IEnumerable<IHierarchicalObject> demoDataObjectEnumerable = new DemoDataObjectEnumerable(demoDataEnumerable);

                GridView1.DataSource = demoDataObjectEnumerable;
                GridView1.DataBind();

                TreeView1.DataSource = new HierarchicalObjectDataSource(demoDataObjectEnumerable);
                TreeView1.DataBind();
            }
        }

        private IEnumerable<DemoData> CreateDemoDataEnumerable()
        {
            DemoData demoData1;
            DemoData demoData2;
            DemoData demoData3;

            List<DemoData> demoDataList = new List<DemoData>();

            demoData1 = new DemoData("AAA", "Id_AAA", "Name_AAA");
            demoDataList.Add(demoData1);

            demoData1 = new DemoData("BBB", "Id_BBB", "Name_BBB");
            demoData2 = new DemoData("DDD", "Id_DDD", "Name_DDD");
            demoData3 = new DemoData("EEE", "Id_EEE", "Name_EEE");
            demoData1.ChildrenList.Add(demoData2);
            demoData2.ChildrenList.Add(demoData3);
            demoDataList.Add(demoData1);

            demoData1 = new DemoData("CCC", "Id_CCC", "Name_CCC");
            demoDataList.Add(demoData1);

            return demoDataList;
        }

        public class DemoData
        {
            // Properties 
            private readonly string _path;

            private readonly string _id;

            private readonly string _name;

            private readonly List<DemoData> _childrenList;


            // Construction 
            public DemoData(string path, string id, string name)
            {
                Require#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
                _path = path;
                _id = id;
                _name = name;
                _childrenList = new List<DemoData>();
            }


            // Member 
            public string Path
            {
                get { return _path; }
            }

            public string Id
            {
                get { return _id; }
            }

            public string Name
            {
                get { return _name; }
            }

            public List<DemoData> ChildrenList
            {
                get { return _childrenList; }
            }
        }

        public class DemoDataObject : DemoData, IHierarchicalObject
        {
            // Properties 
            private readonly string _parentPath;


            // Construction 
            public DemoDataObject(string parentPath, DemoData demoData)
                : base(demoData.Path, demoData.Id, demoData.Name)
            {
                _parentPath = parentPath;

                foreach (DemoData childrenObject in demoData.ChildrenList)
                {
                    this.ChildrenList.Add(childrenObject);
                }
            }


            // Member 
            public string ParentPath
            {
                get { return _parentPath; }
            }
        }

        public class DemoDataObjectEnumerable : IEnumerable<DemoDataObject>, IEnumerable<IHierarchicalObject>
        {
            // Properties 
            private readonly string _parentPath;

            private readonly IEnumerable<DemoData> _demoDataEnumerable;


            // Construction 
            public DemoDataObjectEnumerable(IEnumerable<DemoData> demoDataEnumerable) : this(null, demoDataEnumerable) { }

            public DemoDataObjectEnumerable(string parentPath, IEnumerable<DemoData> demoDataEnumerable)
            {
                Require#region Require

                if (demoDataEnumerable == null) throw new ArgumentNullException();

                #endregion
                _parentPath = parentPath;
                _demoDataEnumerable = demoDataEnumerable;
            }
            

            // Member 
            public IEnumerator<DemoDataObject> GetEnumerator()
            {
                return new DemoDataObjectEnumerator(_parentPath, _demoDataEnumerable.GetEnumerator());
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }

            IEnumerator<IHierarchicalObject> IEnumerable<IHierarchicalObject>.GetEnumerator()
            {
                return (IEnumerator<IHierarchicalObject>)this.GetEnumerator();
            }
        }

        public class DemoDataObjectEnumerator : IEnumerator<DemoDataObject>, IEnumerator<IHierarchicalObject>
        {
            // Properties 
            private readonly string _parentPath;

            private readonly IEnumerator<DemoData> _demoDataEnumerator;

            private DemoDataObject _currentObject = null;

            private IEnumerator<DemoDataObject> _currentChildrenEnumerator = null;


            // Construction 
            public DemoDataObjectEnumerator(string parentPath, IEnumerator<DemoData> demoDataEnumerator)
            {
                Require#region Require

                if (demoDataEnumerator == null) throw new ArgumentNullException();

                #endregion
                _parentPath = parentPath;
                _demoDataEnumerator = demoDataEnumerator;                  
            }

            public void Dispose()
            {
                
            }


            // Member 
            public DemoDataObject Current
            {
                get { return _currentObject; }
            }

            object System.Collections.IEnumerator.Current
            {
                get { return this.Current; }
            }

            IHierarchicalObject IEnumerator<IHierarchicalObject>.Current
            {
                get { return this.Current; }
            }

            public bool MoveNext()
            {
                if (_currentObject != null)
                {
                    if (_currentChildrenEnumerator.MoveNext() == true)
                    {
                        _currentObject = _currentChildrenEnumerator.Current;
                        return true;
                    }
                }

                if (_demoDataEnumerator.MoveNext() == true)
                {
                    _currentObject = new DemoDataObject(_parentPath, _demoDataEnumerator.Current);
                    _currentChildrenEnumerator = new DemoDataObjectEnumerator(_currentObject.Path, _currentObject.ChildrenList.GetEnumerator());
                    return true;
                }

                _currentObject = null;
                _currentChildrenEnumerator = null;
                return false;
            }

            public void Reset()
            {
                _demoDataEnumerator.Reset();
                _currentObject = null;
                _currentChildrenEnumerator = null;
            }
        }        
    }    
}

DataTable資料繫結 :

DataTable資料繫結,主要是使用Adapter這個Pattern來將DataSet資料做轉接處理。


namespace WebApplication1
{
    public partial class WebForm2 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.IsPostBack == false)
            {
                DataTable demoDataTable = this.CreateDemoDataTable();

                IEnumerable<IHierarchicalObject> demoDataObjectEnumerable = new DemoDataObjectEnumerable(demoDataTable);

                GridView1.DataSource = CreateDemoDataTable();
                GridView1.DataBind();

                TreeView1.DataSource = new HierarchicalObjectDataSource(demoDataObjectEnumerable);
                TreeView1.DataBind();
            }
        }

        private DataTable CreateDemoDataTable()
        {
            DataRow dataRow;

            DataTable demoDataTable = new DataTable();
            demoDataTable.Columns.Add("ParentPath", typeof(string));
            demoDataTable.Columns.Add("Path", typeof(string));
            demoDataTable.Columns.Add("Id", typeof(string));
            demoDataTable.Columns.Add("Name", typeof(string));

            dataRow = demoDataTable.NewRow();
            dataRow["ParentPath"] = null;
            dataRow["Path"] = "AAA";
            dataRow["Id"] = "Id_AAA";
            dataRow["Name"] = "Name_AAA";
            demoDataTable.Rows.Add(dataRow);

            dataRow = demoDataTable.NewRow();
            dataRow["ParentPath"] = null;
            dataRow["Path"] = "BBB";
            dataRow["Id"] = "Id_BBB";
            dataRow["Name"] = "Name_BBB";
            demoDataTable.Rows.Add(dataRow);

            dataRow = demoDataTable.NewRow();
            dataRow["ParentPath"] = null;
            dataRow["Path"] = "CCC";
            dataRow["Id"] = "Id_CCC";
            dataRow["Name"] = "Name_CCC";
            demoDataTable.Rows.Add(dataRow);

            dataRow = demoDataTable.NewRow();
            dataRow["ParentPath"] = "BBB";
            dataRow["Path"] = "DDD";
            dataRow["Id"] = "Id_DDD";
            dataRow["Name"] = "Name_DDD";
            demoDataTable.Rows.Add(dataRow);

            dataRow = demoDataTable.NewRow();
            dataRow["ParentPath"] = "DDD";
            dataRow["Path"] = "EEE";
            dataRow["Id"] = "Id_EEE";
            dataRow["Name"] = "Name_EEE";
            demoDataTable.Rows.Add(dataRow);

            return demoDataTable;
        }

        public class DemoDataObject : IHierarchicalObject
        {
            // Properties 
            private readonly DataRow _dataRow;


            // Construction 
            public DemoDataObject(DataRow dataRow)
            {
                Require#region Require

                if (dataRow == null) throw new ArgumentNullException();

                #endregion
                _dataRow = dataRow;
            }


            // Member 
            public string ParentPath
            {
                get { return _dataRow["ParentPath"] as string; }
            }

            public string Path
            {
                get { return _dataRow["Path"] as string; }
            }

            public string Id
            {
                get { return _dataRow["Id"] as string; }
            }

            public string Name
            {
                get { return _dataRow["Name"] as string; }
            }
        }

        public class DemoDataObjectEnumerable : IEnumerable<DemoDataObject>, IEnumerable<IHierarchicalObject>
        {
            // Properties 
            private readonly DataTable _demoDataTable;


            // Construction 
            public DemoDataObjectEnumerable(DataTable demoDataTable)
            {
                Require#region Require

                if (demoDataTable == null) throw new ArgumentNullException();

                #endregion
                _demoDataTable = demoDataTable;
            }


            // Member 
            public IEnumerator<DemoDataObject> GetEnumerator()
            {
                return new DemoDataObjectEnumerator(_demoDataTable.Rows.GetEnumerator());
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }

            IEnumerator<IHierarchicalObject> IEnumerable<IHierarchicalObject>.GetEnumerator()
            {
                return (IEnumerator<IHierarchicalObject>)this.GetEnumerator();
            }
        }

        public class DemoDataObjectEnumerator : IEnumerator<DemoDataObject>, IEnumerator<IHierarchicalObject>
        {
            // Properties 
            private readonly IEnumerator _dataRowEnumerator;            

            private DemoDataObject _currentObject = null;


            // Construction 
            public DemoDataObjectEnumerator(IEnumerator dataRowEnumerator)
            {
                Require#region Require

                if (dataRowEnumerator == null) throw new ArgumentNullException();

                #endregion
                _dataRowEnumerator = dataRowEnumerator;
            }

            public void Dispose()
            {

            }


            // Member 
            public DemoDataObject Current
            {
                get { return _currentObject; }
            }

            object System.Collections.IEnumerator.Current
            {
                get { return this.Current; }
            }

            IHierarchicalObject IEnumerator<IHierarchicalObject>.Current
            {
                get { return this.Current; }
            }

            public bool MoveNext()
            {
                if (_dataRowEnumerator.MoveNext() == true)
                {
                    _currentObject = new DemoDataObject(_dataRowEnumerator.Current as DataRow);
                    return true;
                }
                
                _currentObject = null;
                return false;
            }

            public void Reset()
            {
                _dataRowEnumerator.Reset();
            }
        }
    }
} 
期許自己
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。