DataBinding - Master Detail應用

  • 5604
  • 0

摘要:DataBinding - Master Detail應用

思考一下以下需求需要花多少時間來完成?以NorthWind資料庫為例,有3張table:Customers、Orders、Order Details,users希望可以選取客戶後顯示其相關資訊以及該客戶的訂單,選取某一筆訂單後顯示該訂單的明細,如下圖:

 

NorthWind資料庫載點:http://archive.msdn.microsoft.com/northwind/Release/ProjectReleases.aspx?ReleaseId=1401

透過data binding你會發現簡單到不行,code少到令人訝異,開工吧!

 

UI Layout的部份除了顯示客戶的ComboBox、訂單DataGridView、訂單明細DataGridView,其餘的TextBox是用來顯示跟客戶相關的資訊,例如:電話、地址、傳真號碼…只要是Customers table有的你都可以透過TextBox的data binding來顯示。

  • 存取資料庫:

這裡是使用Linq To SQL當然你也可以用SqlClient來做,不過為了順便介紹Linq To SQL所以就是它了!

在專案按右鍵 【Add】→【New Item】,在Add New Item視窗的左窗格選取【Data】然後在右邊選取【LINQ To SQL Classes】,如下圖:

Name命名為NorthWind.dbml,輸入完成後按Add後畫面會出現NorthWind.dbml的O/R Desinger (Object Relational Designer),這個視覺化的介面是讓你可以用拖曳的方式去建立LINQ To SQL的Entity Classes,來源就是NorthWind資料庫的Tables所以先把NorthWind加到Server Explorer這樣我們才能拖曳我們所要的table並建立對應的entity,如果你的Visual Studio左邊沒有看到Server Explorer,你可以到【View】→【Server Explorer】把它顯示出來。

  • 加入Data Connection:

【Server Explorer】→【Data Connections】按右鍵,選【Add Connection】

在【Choose Data Source】對話方塊選取【Microsoft SQL Server】,按【Continue】

選取Server Name,輸入登入的帳號/密碼最後選擇要連線的資料庫,然後按【Test Connection】確認連線是否成功。

  • O/R Desinger加入Entity Classes

點擊兩下【NorthWind.dbml】開啟O/R Designer,從【Server Explorer】→【DataConnections】→【剛加入的Server】→【Tables】拖曳【Customers】【Orders】【Order Details】到O/R Designer,此時Visual Studio會在【NorthWind.desinger.cs】自動幫你建立對應的Entity Classes

  • 動手寫code

因為DataContext.GetTable傳回來的是Table<TEntity>的物件沒辦法直接轉成DataTable所以我寫了一個Extenion Method來把它轉成DataTable (DataContext.GetTable<TEntity>().ToList()再轉成DataTable):

public static class Extensions
{
    public static DataTable ToDataTable(this IList data)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable(typeof(T).Name);
        foreach (PropertyDescriptor prop in properties)
        {
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
            {
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            }
            table.Rows.Add(row);
        }
        return table;
    }
}

接下來就是如何設定data binding和建立Table間的relation:

private void MasterDetail_Load(object sender, EventArgs e)
{
    NorthWindDataContext dc = new NorthWindDataContext();
    DataSet ds = new DataSet("CustomerOrders");
    // Add Customer, Order and Order detail tables
    ds.Tables.Add(dc.GetTable().ToList().ToDataTable());
    ds.Tables.Add(dc.GetTable().ToList().ToDataTable());
    ds.Tables.Add(dc.GetTable().ToList().ToDataTable());
    // Create data relation between customer and order
    ds.Relations.Add("CustomerOrderRelation", 
        ds.Tables["Customer"].Columns["CustomerID"], ds.Tables["Order"].Columns["CustomerID"]);
    // Create data relation between order and order detail
    ds.Relations.Add("OrderDetailRelation", 
        ds.Tables["Order"].Columns["OrderID"], ds.Tables["Order_Detail"].Columns["OrderID"]);

    // Set data binding
    this.uxOrderGrid.DataSource = ds.DefaultViewManager;
    this.uxOrderGrid.DataMember = "Customer.CustomerOrderRelation";
    this.uxOrderDetailGrid.DataSource = ds.DefaultViewManager;
    this.uxOrderDetailGrid.DataMember = "Customer.CustomerOrderRelation.OrderDetailRelation";

    this.uxName.DataSource = ds.DefaultViewManager;
    this.uxName.DisplayMember = "Customer.CompanyName";
    this.uxName.ValueMember = "Customer.CustomerID";

    this.uxAddress.DataBindings.Add("Text", ds.DefaultViewManager, "Customer.Address");
    this.uxPhone.DataBindings.Add("Text", ds.DefaultViewManager, "Customer.Phone");
}

 

需要寫code的部份真的令人意外的少!