文/趙睿
Datagridview是C#程序中強大的數(shù)據(jù)控件,可以以表格形式將數(shù)據(jù)顯示給用戶,同時允許用戶在該控件上進行數(shù)據(jù)編輯。在GBC開發(fā)過程中,應用了許多Datagridview的相關功能。但當綁定數(shù)據(jù)后,DataGridView在編輯時經常會拋出異常。在此以控制點編輯界面為例,探討Datagridview控件拋出異常的原因及解決辦法。
Datagridview顯示數(shù)據(jù)采用了綁定數(shù)據(jù)源,然后按照列名將各項數(shù)據(jù)顯示在所需的列的方法。這種方法在綁定數(shù)據(jù)時簡便易行。但是在試圖對Datagridview進行編輯或者修改時碰到了諸多問題。因為datagridview占用的線程屬于能夠與用戶交互的線程(簡稱UI線程)如:按鈕、輸入框等。這類控件為了可以隨時響應用戶的操作信息,處在一個類似“一直在線”的狀態(tài)。為了保證線程安全以及提高代碼的運行效率,微軟禁止了從非創(chuàng)建這個控件的線程中訪問這個控件。
解決該問題的辦法主要有兩種:一、把控件的CheckForIllegalCrossThreadCalls屬性設置為false來允許不同線程對控件進行操作。但是如果采用這種辦法,在有兩個或多個線程操作這一控件的狀態(tài)時,則可能會迫使該控件進入一種不一致的狀態(tài)。還可能出現(xiàn)其他與線程相關的 bug,包括爭用情況和死鎖。二、引用命名空間System.Threading,將涉及更新控件的代碼封裝成一個方法,通過Invoke或者BeginInvoke調用。
System.Threading 命名空間提供了大量可以進行多線程編程的類和接口??梢詫崿F(xiàn)如獲取當前進程狀態(tài),掛起線程,阻塞調用線程直至某個線程終止等多種功能。包括進度條,指定時間間隔等操作都需要引用該命名空間。這里要用到其中的Invoke()方法。Invoke方法首先檢查發(fā)出調用的線程(即當前線程)是不是UI線程,如果是,直接執(zhí)行委托指向的方法,如果不是,它將切換到UI線程,然后執(zhí)行委托指向的方法。不管當前線程是不是UI線程,Invoke都阻塞直到委托指向的方法執(zhí)行完畢,然后切換回發(fā)出調用的線程,返回。保證程序的正常運行。
在編輯界面加入Datagridview控件,命名為dataGridViewX1。創(chuàng)建一個記錄所有控制點相關信息的全局變量DataTable,命名為dt。dataGridViewX1綁定dt作為數(shù)據(jù)源。在用戶對datagridview顯示的數(shù)據(jù)進行編輯、刪除、添加等操作時,保證該datatable的數(shù)據(jù)也進行相同操作。使datagridview與datatable始終保持同步。最后保存數(shù)據(jù)時,可以直接獲得該datatable做最終的數(shù)據(jù)。
輸入以下代碼:MyInvoke mi = new MyInvoke(DataGridViewBound);
其中數(shù)據(jù)綁定(DataGridViewBound)中可以將之前的數(shù)據(jù)源綁定和列數(shù)據(jù)綁定添加進來。
之后,如果需要對控制點數(shù)據(jù)進行編輯修改,只要對dt進行相關修改后引用代碼:
就可以實現(xiàn)dataGridViewX1顯示的數(shù)據(jù)與dt的同步,不會因為dataGridViewX1已綁定數(shù)據(jù)而報錯。
按照程序需求,在dataGridViewX1中“參考橢球”、“參考框架”和“高程系統(tǒng)”這三個列可以點擊后出現(xiàn)下拉菜單,從中選擇相應的選項。這三個列要求基本相同,以下以“參考橢球”列為例。
在窗體中添加comboBox控件,命名為cmbellipsoid,
作為控制點基準的“參考橢球”在數(shù)據(jù)庫中是以其ID號記錄的。而相關信息顯示在數(shù)據(jù)表格上時則應該顯示其名稱。這里需要利用數(shù)據(jù)庫中“Ellipsoid”表將“參考橢球”的ID號與名稱關聯(lián)起來。此外“Ellipsoid”表也作為cmbellipsoid的數(shù)據(jù)源。
下拉控件初始設置為不可見,在鼠標點擊相應的單元格時,判斷鼠標點擊是否為所在列。如果符合要求,則使下拉控件在單元格內可見,大小與單元格相同。
在鼠標點擊單元格事件中輸入以下代碼:
//獲取所選單元格的值,保證在顯示下拉菜單時,下拉菜單中所選的值與所選單元格的值相同,最后使下拉菜單可見
在離開單元格時,將用戶已選則的選項寫入dt,并使下拉菜單不可見。在鼠標離開單元格事件中添加以下代碼:
如果用戶在點開下拉菜單后沒有進行選擇,直接拖動滾動條,會看見下拉菜單始終保持在初始顯示的位置,與所選單元格脫離。
在dataGridViewX1的拖動滾動條事件中添加以下代碼:this.cmbellipsoid.Visible = false;保證在拖動滾動條時,下拉菜單是隱藏的。
在datagridview中點擊右鍵可以顯示菜單,以下以“刪除”功能為例,講解實現(xiàn)方法。
首先添加contextMenuStrip1控件,將dataGridViewX1的ContextMenuStrip屬性設置為contextMenuStrip1。并在contextMenuStrip1控件中添加“刪除”欄。在點擊“刪除”欄的事件中獲取dataGridViewX1當前具有焦點單元格的控制點信息,刪除數(shù)據(jù)庫中與之相同的數(shù)據(jù)。
該方法中獲得信息的當前具有焦點單元格可能會與用戶實際想要刪除的單元格不符。例如:鼠標選中第一行后,在第二行點擊右鍵。第一行仍然是被選中狀態(tài),代碼獲取的控制點信息就是第一行的。因此,應當在dataGridViewX1的CellMouseDown事件中添加代碼,保證右鍵點擊時,鼠標所點的單元格即為焦點單元格。
Datagridview數(shù)據(jù)源綁定datable后按照上文方法進行了編寫,程序應用達到了預期效果,界面簡單易懂,操作方便。之后也在該GBC程序其他其他界面廣泛應用。
物探測量需求推動著GNSS技術與數(shù)據(jù)處理的不斷進步。GNSS的多種測量模式也愈加成熟。該款GNSS軟件針對石油物探測量,擁有廣大的應用需求。
參考文獻
[1]季宇虹,王讓會.全球導航定位系統(tǒng)GNSS的技術與應用[J].全球定位系統(tǒng),2010(05):69-75.
[2]王偉.基于C#技術的對賬系統(tǒng)設計與實現(xiàn)[J].科技創(chuàng)新與生產力,2013(09):76-79.
[3]朱瑞芳.DataGridView控件應用示例[J].電腦知識與技術,2015(25):189-191.