[ASP.NET] : HierarchicalObjectDataSource Part2
前言 :
之前發布了一篇[ASP.NET] : HierarchicalObjectDataSource
本篇是它的Part2,內容沒有新的東西。
只是把上一篇發表的物件,套用一些Design Patterns。
來達到異種資料的資料繫結。
一般寫ASP.NET使用TreeView,大多使用XmlDataSource或是SiteMapDataSource做資料繫結,不然就是依照資料去程式動態建立TreeNode。
HierarchicalObjectDataSource 封裝了階層式資料繫結的複雜運算,讓TreeView的資料繫結開發變的可行。
依照這兩篇HierarchicalObjectDataSource的文章思路繼續開發下去,相信會有更多的延伸應用。
執行結果 :
下圖為底下所有範例程式碼執行的結果。上半部表格將資料內容條列 ,下半部樹狀選單將資料內容顯示為樹狀。
樹狀物件資料繫結 :
樹狀物件資料繫結,主要是使用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();
}
}
}
}
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。