今天我們要做的是以CSV為資料來源的資料來源控制項。我簡化了MSDN的範例,讓我們專注在資料來源控制項的最根本機制上。
資料來源控制項是一種沒有視覺化界面的控制項,也就是說,它並不需要使用者介面來作呈現,因為他只負責對其他控制項提供資料來源。
當我們要對多個物件做協調或溝通的時候,需要一個管理的介面,在這邊分別是IDataSource.GetViewNames和IDataSource.GetView。
IDataSource.GetViewNames 負責取得資料來源的各個物件名稱。
IdataSource.GetView負責取得指定的資料來源。
View實際上指的是DataSourceView的,這是一個抽象類別,你必須實作你想要提供的動作,這邊我們實作ExecuteSelect。
CsvDataSource的屬性可以供開發人員來做設定,而真正對資料來源操作的是CsvDataSourceView,我們把這兩項屬性的存取交給他來負責。
CsvDataSource只負責由CsvDataSourceView中取得屬性值,本身並不負責保存這些屬性值。
[ToolboxData("<{0}:CsvDataSource runat=server></{0}:CsvDataSource>")]public class CsvDataSource : DataSourceControl{public CsvDataSource() : base() { }public string SourceFile{get { return (this.GetView(string.Empty) as CsvDataSourceView).SourceFile; }set{if ((this.GetView(string.Empty) as CsvDataSourceView).SourceFile != value){(this.GetView(string.Empty) as CsvDataSourceView).SourceFile = value;RaiseDataSourceChangedEvent(EventArgs.Empty);}}}public bool IncludesColumnNames{get { return (this.GetView(string.Empty) as CsvDataSourceView).IncludesColumnNames; }set{if ((this.GetView(string.Empty) as CsvDataSourceView).IncludesColumnNames != value){(this.GetView(string.Empty) as CsvDataSourceView).IncludesColumnNames = value;RaiseDataSourceChangedEvent(EventArgs.Empty);}}}private CsvDataSourceView view = null;protected override DataSourceView GetView(string viewName){if (null == view){view = new CsvDataSourceView(this, string.Empty);}return view;}protected override System.Collections.ICollection GetViewNames(){ArrayList al = new ArrayList(1);al.Add(CsvDataSourceView.DefaultViewName);return al as ICollection;}}
在繼承的DataSourceView中,我們使用ExecuteSelect來取得資料。在MSDN中,是如此描述ExecuteSelect和Select:
ExecuteSelect:從基礎資料儲存區取得資料清單。
Select:從基礎資料儲存區非同步取得資料清單。
其他的Update、Insert、Delete也一樣是在 DataSourceView 物件表示的資料清單上,執行『非同步』作業。
public class CsvDataSourceView : DataSourceView{public CsvDataSourceView(IDataSource owner, string viewName): base(owner, DefaultViewName){ }public static string DefaultViewName = "CommaSeparatedView";private string sourceFile = string.Empty;internal string SourceFile{get { return sourceFile; }set{sourceFile = HttpContext.Current.Server.MapPath(value);}}private bool includesColumnNames = false;internal bool IncludesColumnNames{get { return includesColumnNames; }set { includesColumnNames = value; }}protected override System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments){if (File.Exists(this.SourceFile)){DataTable dt = new DataTable();using (StreamReader sr = new StreamReader(SourceFile)) {string[] dataValues;DataColumn col;dataValues = sr.ReadLine().Split(',');foreach (string token in dataValues){col = new DataColumn(token, typeof(string));dt.Columns.Add(col);}if (!IncludesColumnNames){dt.Rows.Add(dataValues);}string s = string.Empty;while(( s = sr.ReadLine()) != null){dataValues = s.Split(',');dt.Rows.Add(dataValues);}}dt.AcceptChanges();DataView dv = new DataView(dt);if (arguments.SortExpression != string.Empty){dv.Sort = arguments.SortExpression;}return dv;}return null;}}
測試的檔案(sample.csv):
ID,Title,Channel,Program
1,台灣奇案,第一頻道,大目神
2,戲說台灣,第二頻道,蓋杯娘
網頁中的使用方式:
<asp:GridView ID="GridView1" DataSourceID="CsvDataSource1" runat="server"></asp:GridView><cc1:CsvDataSource ID="CsvDataSource1" runat="server"IncludesColumnNames="true" SourceFile="sample.csv"></cc1:CsvDataSource>
參考資料:
沒有留言:
張貼留言