轉帖|使用教程|編輯:龔雪|2014-03-17 13:43:08.000|閱讀 2616 次
概述:雖然網上關于主從表(Master-Detail)如何動態加載明細表數據的文章很多了,但都不是很系統,本文再進行一下詳細的總結。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
主從表(Master-Detail)動態加載明細表效果如下圖:
實現過程說明如下:
1、程序開始時只加載主表的數據,明細表內容不加載;
2、如果選擇了新的主表對象,根據新主表對象ID,動態從數據庫中加載相關明細表的數據,并合并到數據源的明細表中,同時把該主表的ID在List中緩存(以避免重復加載);
下面以nwind.mdb數據庫中的Orders和Order Details主從表為列說明具體過程。
做到一半發現MDB數據不支持DataSet一些特性,感覺很不爽,臨時更換為SQL數據庫,使用SQL 2005示例數據庫AdventureWorksDB,以Sales.SalesOrderHeader和Sales.SalesOrderDetail為例說明具體過程。
DevExpress DXperience教程教程環境必備:
1、SQL 2005示例數據庫AdventureWorksDB下載及安裝,可以下載并安裝;
2、IDE環境:VS.Net2008;
3、DXperience組件版本:9.2.6
代碼只用來說明問題,沒有詳細的錯誤處理機制等。
1、運行VS環境,并建立一個解決方案;
2、如果您沒有示例數據庫,可以到上面的下載地址去下載并安裝;
3、主窗體SmarTestMain中加入一個GridControl,并建立兩個視圖,名稱及關系如下圖所示:
4、向項目中添加一個DataSet數據集DSSalesOrder.xsd,添加一個到AdventureWorks數據庫的連接,如下圖所示:
5、把表SalesOrderHeader和SalesOrderDetail拖到DataSet設計器,自動建立關系,重新命名關系SOHeaderDetail,如下圖所示:
6、修改dataset中表SalesOrderDetail的查詢,在Fill,GetData()上點擊右鍵彈出菜單,選擇Configure,彈出配置窗體,在select語句后面加上查詢條件
where [email=SalesOrderID=@SalesOrderId]SalesOrderID=@SalesOrderId[/email]
下一 步;方法名稱修改為
FillBySalesOrderId/GetDataFillBySalesOrderId;
下一步結束。
7、設置gridControl1的數據源并設置其DataMember=SalesOrderHeader,在grindControl1的Level1上點擊,并選擇菜單Change LevelName,設置levelname=SOHeaderDetail,注意與數據集中定義的關系是一致的,如下圖所示:
8、運行GridControlRunDesigner,選擇明細表視圖gvOrderDetails,點擊Columns/Retrieve Fields以自動生成明細視圖的列,將兩個gridViewOptionsView.ColumnAutoWidth=false。
9、接下來的任務是寫個簡單的數據訪問類,包括兩個方法,如下所示:
public static DSSalesOrder getSalesOrderAll() { DSSalesOrder dataSet = new DSSalesOrder(); using (SqlConnection con = new SqlConnection(Properties.Settings.Default.AdventureWorksConnectionString)) { using (DSSalesOrderTableAdapters.SalesOrderHeaderTableAdapter ta = new SmarTest.Template.DSSalesOrderTableAdapters.SalesOrderHeaderTableAdapter { Connection = con }) { ta.Fill(dataSet.SalesOrderHeader); } } return dataSet; } public static DSSalesOrder getSalesOrderDetailByOrderId(int salesOrderId) { DSSalesOrder dataSet = new DSSalesOrder(); using (SqlConnection con=new SqlConnection(Properties.Settings.Default.AdventureWorksConnectionString)) { using (DSSalesOrderTableAdapters.SalesOrderDetailTableAdapter ta = new SmarTest.Template.DSSalesOrderTableAdapters.SalesOrderDetailTableAdapter { Connection = con }) { ta.FillBySalesOrderId(dataSet.SalesOrderDetail, salesOrderId); } } return dataSet; }
關鍵是第二個方法,不是返回所有明細數據,而是根據主表ID,返回相關的明細。
下面的步驟都很關鍵,一定要注意!
10、設置主表視圖 gvOrders屬性:
this.gvOrders.OptionsDetail.AllowExpandEmptyDetails = true;(此屬性在整個項目中起一個核心的作用,如果不設置此屬性,即使其它都正確,還是不會引發gvOrders_MasterRowGetChildList事件。)
this.gvOrders.OptionsDetail.AllowOnlyOneMasterRowExpanded = true;(可以不設置)
this.gvOrders.OptionsBehavior.Editable = false;(這里是因為使用了RowClick事件,二者有關系,所以設置)
12、gvOrders視圖必須響應的事件
List<int> mSalesOrderCach = new List<int>(); int mSalesOrderId = -1; private void gvOrders_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) { var row = gvOrders.GetDataRow(e.RowHandle) as DSSalesOrder.SalesOrderHeaderRow; mSalesOrderId = row.SalesOrderID; gvOrders.ExpandMasterRow(e.RowHandle);//此語句非必須,主要是使新的主表焦點行立即展開明細表,即使不包括數據。否則需要點擊主表的焦點行的“+”展開。 } private void gvOrders_MasterRowGetChildList(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetChildListEventArgs e) { if (mSalesOrderCach.Contains(mSalesOrderId)) return; using (DevExpress.Utils.WaitDialogForm wdf = new DevExpress.Utils.WaitDialogForm("向服務器請求數據...")) { var dsSalesOrder = gridControl1.DataSource as DSSalesOrder; using (DSSalesOrder ds=dbHelper.getSalesOrderDetailByOrderId(mSalesOrderId)) { if(ds.SalesOrderDetail.Rows.Count>0) { mSalesOrderCach.Add(mSalesOrderId); dsSalesOrder.SalesOrderDetail.Merge(ds.SalesOrderDetail); } } } }
怎樣才能不顯示子表的 ViewCaption?
設置主表視圖
gvOrders.gvOrders.OptionsDetail.ShowDetailTabs = false;
即可
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都控件網