關于DataGrid的動態排序問題
2024-07-21 02:22:55
供稿:網友
 
我有這么一個設計界面的設計習慣:我喜歡把數據庫的”comment”字段從任何顯示數據庫列表的控件中過濾掉,然后通過跟蹤用戶鼠標的單擊,動態地將它的內容顯示在旁邊另一塊我覺得更適合顯示它的地方,比如說一個editbox(multiline = true)。以前這個方法動作得很好,因為我沒有采用datagrid,而是用的像listbox一樣的控件,但datagrid強大的功能反而給我出了一道難題。因為在datagrid的界面上用戶可以通過點擊columnheader來改變數據顯示的排列順序。而在我的代碼里頭,剛開始只能通過重寫mousedown的事件,利用datagrid的當前行的行號或者叫索引來安排從本地dataview中讀取數據并顯示在其它地方。后來我發現,當用戶點擊columnheader以后數據在datagrid中的排列順序改變了,在旁邊顯示出來的信息,比如comment,就對不上號了。
后來我發現,每次點擊gatagrid的columnheader后,它上面的小箭頭都會改變方向,但每個columnheader的箭頭方向是獨立的。說它們是獨立的是因為每列的箭頭都只有被點擊后才會改變方向,如果點擊的是另一個列,那么這將對本列沒有影響。舉個列子,有如下兩個列,從箭頭的方向來看,數據是按id列升序排列的:
id∧ name
現在用戶點擊了第一個columnheader,結果將變成下面這種情況:
id∨ name
這個時候如果用戶繼續點擊第一列,那么它的箭頭方向將變為向上,而點擊后者,其箭頭方向會變成設下,而不是向上,因為它默認的就是升序排列。
如果有一個方法讓這些箭頭都統一起來,我就可以通過動態地改變dataview的sort屬性來對應新的排列順序,因為通過捕獲datagrid的mousedown事件我可以獲取被點擊的columnheader的headertext。
 那么怎樣使這些箭頭都統一起來呢?
 用一個布爾變量!
 是的,就這個簡單,但想到可不容易。于是我在當前窗體類中設置了一個布爾變量,取名為bsortdesc并將之初始為了false,因為這是默認的。那么接下來,當用戶點擊“列頭”時,我就在datagrid的mousedown事件中通過代碼得到當前列的列名。將布爾變量作一個逆變換后判斷它的值,以決定將dataview的sort屬性改成什么。這樣一來,后臺的數據視圖就會動態地跟隨前臺的變量而改變順序。于是乎,顯示在旁邊的其它數據也就可以對上號了。
 下面用一段代碼再作一翻解釋:
//在form1類的定義中聲明一個受保護的布爾變量
private bool bsortdesc = false;
//在form1_load中初始化
 sqlcommand cmd = global.cnn.createcommand();
 cmd.commandtext = "spgetempinfo";
 cmd.commandtype = commandtype.storedprocedure;
 this.da = new sqldataadapter(cmd);
 this.ds = new dataset();
 this.dv = new dataview();
 this.da.fillschema(this.ds, schematype.source);
 this.da.fill(this.ds, "tblempinfo");
 this.dv.table = this.ds.tables["tblempinfo"];
 this.dv.sort = "id";
 this.dg.datasource = this.dv
 datagridtablestyle ts = new datagridtablestyle();
 ts.mappingname = "tblempinfo";
 this.dg.tablestyles.add(ts);
 this.dg.tablestyles[0].gridcolumnstyles["comment"].width = 0;
//下面是datagrid的mousedown事件
 private void dgdoc_mousedown(object sender, system.windows.forms.mouseeventargs e)
 {
 datagrid tmpdg = (datagrid)sender;
 datagrid.hittestinfo hti = tmpdg.hittest(e.x, e.y);
 switch(hti.type)
 { 
 case datagrid.hittesttype.columnheader:
 {
 try
 {
 int ncolumnindex = hti.column;
 string strcolumnheader = this.dg.tablestyles[0].gridcolumnstyles[ncolumnindex].headertext;
 this.bsortdesc = !this.bsortdesc;
 if (this.bsortdesc)
 {
 this.dv.sort = strcolumnheader + " asc";
 }
 else
 {
 this.dv.sort = strcolumnheader + " desc";
 }
 }
 catch(exception ex)
 {
 messagebox.show(ex.message);
 }
 }break;
 }
 }
//如果您選擇將某些字段在datagrid之外顯示并將它們與數據源綁定在一起時,請加入以下的currentcellchanged事件處理代碼
 private void dgdoc_currentcellchanged(object sender, system.eventargs e)
 {
 // now the dg row index can be treated as the row index of the data in
 // dv since dv has been re-sorted
 bindingcontext[this.].position = this.dg.currentrowindex;
 this.updatescreen();
 }
//最后是更新界面的方法(rtb代表richtextbox)
 private void updatescreen()
 {
 this.rtbcomment.clear();
 this.rtbcomment.text = this.dv[bindingcontext[this.dv].position]["comment"].tostring();
 
這樣,當你點擊datagrid的columnheader時,上面箭頭的方向總是一上一下,即使你點擊在不同的列上.而至于后臺的視圖,已經動態地重新排列了.
這是我自己想出來的方法,可能有不足之處,如果誰有更好的方法,希望能和大家分享d:)