2011年5月29日 星期日

實作資料來源控制項(DataSourceControl)

今天我們要做的是以CSV為資料來源的資料來源控制項。我簡化了MSDN的範例,讓我們專注在資料來源控制項的最根本機制上。

資料來源控制項是一種沒有視覺化界面的控制項,也就是說,它並不需要使用者介面來作呈現,因為他只負責對其他控制項提供資料來源。

當我們要對多個物件做協調或溝通的時候,需要一個管理的介面,在這邊分別是IDataSource.GetViewNames和IDataSource.GetView。

IDataSource.GetViewNames 負責取得資料來源的各個物件名稱。

IdataSource.GetView負責取得指定的資料來源。

View實際上指的是DataSourceView的,這是一個抽象類別,你必須實作你想要提供的動作,這邊我們實作ExecuteSelect。

CsvDataSource的屬性可以供開發人員來做設定,而真正對資料來源操作的是CsvDataSourceView,我們把這兩項屬性的存取交給他來負責。

CsvDataSource只負責由CsvDataSourceView中取得屬性值,本身並不負責保存這些屬性值。

image

 

[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>        


參考資料:



沒有留言:

張貼留言