熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

新數據網格簡介

2013-11-13 10:30:23  來源: .NET編程 

  新的 DataGridView 是 NET 中的一個新控件是針對 NET x 中功能較差的標准 DataGrid 控件而設計的Matthew MacDonald 在本文中論述了許多改進包括DataGridView 支持大量自定義和細致的格式設置靈活的大小調整和選擇更好的性能以及更豐富的事件模型

  net Framework 的前兩個版本(NET NET )在數據綁定方面留下了明顯的空白盡管開發人員擁有一個靈活的可配置模型可以將幾乎所有的控件鏈接到幾乎所有的數據源但卻沒有一種有效的方法來顯示完整的信息表可以實現此目的的唯一工具就是 DataGrid 控件這種控件非常適合於處理簡單的演示但是不太適合實際代碼

  填補這項空白是 NET 的主要目標之一並且 Microsoft 已經用全新的網格控件 DataGridView 來實現此目標DataGridView 有兩個指導原則首先其目標是支持常見任務(如主控/詳細列表驗證和數據格式設置)而不需要您編寫許多代碼更重要的是設計過程中始終考慮了擴展性因此您可以集成所需的專用功能而不必采用低級別的復雜編程

  基本數據綁定

  熟悉 DataGridView 的最佳方法就是實際嘗試一下無需配置任何屬性就像 DataGrid 一樣您可以使用 DataSource 屬性來綁定 DataTable 對象(或從 DataTable 派生的對象)

  Dim ds As DataSet = GetDataSet() DataGridViewDataSource = dsTables(Customers)

  與 DataGrid 不同的是DataGridView 一次只能顯示一個表如果綁定整個 DataSet則不會顯示任何數據除非您使用要顯示的表名設置了 DataMember 屬性

  DataGridViewDataSource = ds DataGridViewDataMember = Customers

  基本的 DataGridView 顯示遵循以下幾項簡單的規則

   ?

  為數據源中的每個字段創建一列

?

  使用字段名稱創建列標題列標題是固定的這意味著用戶在列表中向下移動時列標題不會滾動出視圖

?

  支持 Windows XP 視覺樣式您會注意到列標題具有新式的平面外觀並且當用戶將鼠標移到其上時會突出顯示

  datagridview 還包括幾個您可能不會立即注意到的默認行為

   ?

  允許就地編輯用戶可以在單元格中雙擊或按 F 來修改當前值唯一的例外是將 DataColumnReadOnly 設置為 True 的字段(如當前示例中的 OrderID 字段)

?

  支持自動排序用戶可以在列標題中單擊一次或兩次基於該字段中的值按升序或降序對值進行排序默認情況下排序時會考慮數據類型並按字母或數字順序進行排序字母順序區分大小寫

?

  允許不同類型的選擇用戶可以通過單擊並拖動來突出顯示一個單元格多個單元格或多個行單擊 DataGridView 左上角的方塊可以選擇整個表

?

  支持自動調整大小功能用戶可以在標題之間的列分隔符上雙擊使左邊的列自動按照單元格的內容展開或收縮


美化 DataGridView

  datagridview 的默認外觀僅僅比 DataGrid 略有改進但是使用幾項快速調整功能您可以將其顯著改進

  其中的一個問題就是列無法自動展開以適合其包含的數據您可以使用 DataGridViewAutoSizeColumns() 方法以及 DataGridViewAutoSizeColumnCriteria 枚舉中的某個值來解決此問題您可以選擇根據標題文本當前顯示的行或表中的所有行的的寬度來調整列寬

   根據標題或此列的某一行中 最長一段文本的寬度調整 列寬 DataGridViewAutoSizeColumns( _ DataGridViewAutoSizeColumnCriteriaHeaderAndRows)

  請記住此方法必須在綁定數據後調用否則不會產生任何效果你可能還需要在用戶編輯數據後使用它(可能在響應 DataGridViewCellValueChanged 等事件時)

  如果不增加列寬則可以更改行高默認情況下列中的文本會跨越多行如果您使用 DataGridViewAutoSizeRows() 方法則行會根據其中的內容調整高度使用此方法前您可能希望增加列寬尤其是在字段包含大量文本時例如以下代碼片段使說明列的列寬增加為原列寬的四倍然後調整行高以容納其內容

  DataGridViewColumns(Description)Width *= DataGridViewAutoSizeRows( _ DataGridViewAutoSizeRowsModeHeaderAndColumnsAllRows)

   比較了自動調整 DataGridView 大小的各種方法

  另一個合理的更改是清理每一列中顯示的標題文本例如標題order Date比字段名稱OrderDate看上去更為專業這項更改很容易進行您只需從 DataGridViewColumns 集合中檢索相應的 DataGridViewColumn並修改其 HeaderText 屬性

  DataGridViewColumns(OrderID)HeaderText = Order ID


 
使用 DataGridView 選擇單元格

  默認情況下datagridview 允許自由選擇用戶可以突出顯示單元格或單元格組可以一次突出顯示所有單元格(通過單擊網格右上角的方塊)還可以突出顯示一行或多行(通過在行標題列中單擊)根據選擇模式用戶甚至能夠通過選擇列標題來選擇一列或多列通過使用 DataGridViewSelectionMode 枚舉中的某個值來設置 DataGridViewSelectionMode 屬性可以控制此行為如下所述

   ?

  CellSelect用戶可以選擇單元格但不能選擇整個行或標題如果 DataGridViewMultiSelect 為 True則用戶可以選擇多個單元格

?

  FullColumnSelect單擊列標題只能選擇整個列如果 DataGridViewMultiSelect 為 True則用戶可以選擇多個列使用此模式時單擊列標題不會對網格進行排序

?

  FullRowSelect單擊行標題只能選擇整個行如果 DataGridViewMultiSelect 為 True則用戶可以選擇多個行

?

  ColumnHeaderSelect用戶可以使用 CellSelect 或 FullColumnSelect 選擇模式使用此模式時單擊列標題不會對網格進行排序

?

  RowHeaderSelect用戶可以使用 CellSelect 或 FullRowSelect 選擇模式這是默認的選擇模式

  通過 DataGridView可以使用以下三個屬性方便地檢索選定的單元格SelectedCellsSelectedRows 和 SelectedColumns無論使用的是哪種選擇模式SelectedCells 都始終返回 DataGridViewCell 對象的集合另一方面如果使用行標題選擇了整個行則 SelectedRows 只返回信息而如果使用列標題選擇了整個列則 SelectedColumns 也只返回信息

  例如以下代碼片段將檢查選定的整個行只要找到一行它就會在消息框中顯示 CustomerID 列中的相應值

  For Each SelectedRow As DataGridViewRow In _ DataGridViewSelectedRows MessageBoxShow( _ SelectedRowCells(CustomerID)Value) Next

  使用 CurrentCell 或 CurrentCellAddress 屬性檢索對當前單元格的引用也同樣簡單使用 DataGridView 時您會注意到當前單元格被一個矩形圍住看起來像是一個用黑色虛線繪制的方框這就是用戶當前所在的位置

  currentcelladdress 屬性是只讀的但是您可以使用 CurrentCell 以編程方式更改當前位置完成此操作後DataGridView 將被滾動以使當前位置可見

   移至第十一行的第四個單元格 DataGridViewCurrentCell = _ DataGridViewRows()Cells()


 
DataGridView 對象

  到目前為止您已經了解了如何與當前選定的一組行單元格和列進行交互datagridview 提供了兩個關鍵集合用於處理整個數據集這兩個集合分別是 Columns(DataGridViewColumn 對象的集合)和 Rows(DataGridViewRow 對象的集合每個對象都引用一組 DataGridViewCell 對象的集合) 顯示了對象模型

  一般而言您將使用 DataGridViewColumn 對象來配置列顯示屬性格式設置及標題文本而使用 DataGridViewRow 和 DataGridViewCell 對象從綁定的記錄中檢索實際數據在 DataGridViewCell 中修改數據時處理方式與用戶編輯的方式相同引發相應的 DataGridView 更改事件並且修改底層的 DataTable

  現在您已經了解了 DataGridView 對象模型因此可以輕松地創建遍歷該表的代碼要選擇行列或單元格只需找到對應的 DataGridViewRowDataGridViewColumn 或 DataGridViewCell 對象並將 IsSelected 屬性設置為 True

  以下示例以編程方式選擇 OrderID 字段的值小於 的所有行

  For Each Row As DataGridViewRow In DataGridViewRows If RowCells(OrderID)Value < Then RowSelected = True End If Next

  值得一提的是有幾個從 DataGridViewColumn 派生的不同的類這些類可以控制在單元格中顯示和編輯值的方式NET 包括五個預先創建的 DataGridView 列類DataGridViewButtonColumnDataGridViewCheckBoxColumnDataGridViewComboBoxColumnDataGridViewImageColumn 和 DataGridViewTextBoxColumn

  DataGridView 樣式

  設計 DataGridView 時面臨的挑戰之一就是創建一個格式設置系統該系統要能夠足夠靈活地應用不同級別的格式設置而對於非常大的表又要保持高效從靈活性角度來看最好的方法是允許開發人員分別配置每個單元格但是從效率角度來看這種方法可能是有害的包含數千行的表中具有好幾萬個單元格維護每個單元格的不同格式肯定會浪費很多內存

  為解決此問題datagridview 通過 DataGridViewCellStyle 對象來實現多層模型DataGridViewCellStyle 對象表示單元格的樣式並且包括如顏色字體對齊換行和數據格式等詳細信息您可以創建一個 DataGridViewCellStyle 來指定整個表的默認格式此外還可以指定列行和各個單元格的默認格式格式設置的越細致創建的 DataGridViewCellStyle 對象越多該解決方案的可伸縮性也就越小但是如果您主要使用基於列和基於行的格式設置並且只是偶爾設置各個單元格的格式則與 DataGrid 相比DataGridView 不需要太多內存

  datagridview 應用格式設置時將遵循以下優先順序(從最高到最低)

   DataGridViewCellStyle DataGridViewRowDefaultCellStyle DataGridViewAlternatingRowsDefaultCellStyle DataGridViewRowsDefaultCellStyle DataGridViewColumnDefaultCellStyle DataGridViewDefaultCellStyle

  重要的是要清楚樣式對象不是以全有/全無的方式應用的datagridview 會檢查每個屬性例如假設您的單元格使用 DataGridViewCellStyle 屬性來應用自定義字體但沒有設置自定義前景色結果該字體設置將覆蓋任何其他樣式對象中的字體信息但如果層次結構中下一個樣式對象的前景色不為空則將從該對象繼承前景色(在這種情況下為 DataGridViewRowDefaultCellStyle)

  datagridviewcellstyle 定義了兩種格式設置數據和外觀數據格式設置描述顯示數據綁定值之前如何對其進行修改這種格式設置通常包括使用格式設置字符串將數字或日期值轉換為文本要使用數據格式設置只需使用 DataGridViewCellStyleFormat 屬性設置格式定義或自定義格式字符串即可

  例如以下代碼片段對 UnitCost 字段中的所有數字進行格式設置以將它們顯示為貨幣值保留兩位小數並加上在區域設置中定義的相應貨幣符號

  DataGridViewColumns(UnitCost) _ DefaultCellStyleFormat = C

  外觀格式設置包括顏色和格式等表面細節例如以下代碼右對齊 UnitCost 字段應用粗體並將單元格的背景更改為黃色

  DataGridViewColumns(UnitCost) _ DefaultCellStyleFont = _ New Font(DataGridViewFont FontStyleBold) DataGridViewColumns(UnitCost) _ DefaultCellStyleAlignment = _ DataGridViewContentAlignmentMiddleRight DataGridViewColumns(UnitCost) _ DefaultCellStyleBackColor = ColorLightYellow

  其他與格式設置相關的屬性包括 ForeColorSelectionForeColorSelectionBackColorWrapMode(控制文本在空間允許時是跨越多行還是直接截斷)及 NullValue(將替代 Null 值的值)

  datagridview 還包括一個設計器用於在設計時配置列樣式只需從Properties(屬性)窗口中選擇DataGridView Properties(DataGridView 屬性)鏈接或者從各種預先創建的樣式設置中選擇AutoFormat(自動套用格式)


自定義單元格格式

  單元格格式設置的第一種方法是設置更高級別的 DataGridViewDataGridViewColumn 和 DataGridViewRow 屬性但是有時您需要為特定單元格單獨設置樣式例如您可能需要在列中的數據大於或小於某個值時標記該列中的數據例如突出顯示項目計劃列表中已過去的到期日期或者在銷售分析中突出顯示負收益率在這兩種情況下您需要對單獨的單元格進行格式設置

  了解 DataGridView 對象模型後您可能想要遍歷特定列中的單元格集合以尋找要突出顯示的值這種方法是可行的但不是最好的方法關鍵問題是如果用戶編輯了數據或者如果代碼更改了綁定的數據源不會對單元格的突出顯示情況進行相應的更新

  幸運的是datagridview 針對此目的提供了 CellFormatting 事件CellFormatting 只在顯示單元格值之前引發通過該事件可以基於單元格的內容來更新單元格樣式以下示例檢查特定的客戶並相應地標記單元格

  Private Sub DataGridView_CellFormatting( _ ByVal sender As SystemObject _ ByVal e As SystemWindowsForms _ DataGridViewCellFormattingEventArgs) _ Handles DataGridViewCellFormatting 檢查該列是否正確 If DataGridViewColumns(eColumnIndex)Name = _ CustomerID Then 檢查該值是否正確 If eValue = ALFKI Then eCellStyleForeColor = ColorRed eCellStyleBackColor = ColorYellow End If End If End Sub

  樣式不是影響網格外觀的唯一細節您還可以隱藏列在不同位置之間移動列凍結使這些列在用戶滾動到右端時仍然可見這些功能都是通過 DataGridViewColumn 類的屬性提供的如下所述

   ?

  DisplayIndex設置列在 DataGridView 中顯示的位置例如DisplayIndex 值為 的列將自動顯示在最左邊的列中如果多個列具有相同的 DisplayIndex則先顯示最先出現在該集合中的列因此如果您使用 DisplayIndex 將一列向左移動則可能還需要設置最左邊的列的 DisplayIndex以將其向右移動最初DisplayIndex 與 DataGridViewColumns 集合中 DataGridViewColumn 對象的索引相匹配

?

  Frozen如果為 True則該列將始終可見並且固定在表的左側即使用戶為查看其他列而滾動到右側亦如此

?

  HeaderText設置將在列標題中顯示的文本

?

  Resizableminimumwidth將 Resizable 設置為 False以防止用戶調整列寬或者將 MinimumWidth 設置為允許的最小像素數目

?

  Visible要隱藏列請將此屬性設置為 False


按鈕列

  datagridview 提供的一種列是 DataGridViewButtonColumn這種列在每一項旁邊顯示一個按鈕您可以響應此按鈕的單擊事件並使用它啟動其他操作或顯示新的表單

  以下示例使用按鈕文字details創建簡單的按鈕列

   創建按鈕列 Dim Details As New DataGridViewButtonColumn() DetailsName = Details 關閉數據綁定並顯示靜態文本 (但是您可以通過設置 DataPropertyName 屬性來使用該表中的屬性) DetailsDisplayTextAsFormattedValue = False DetailsText = Details 清除標題 DetailsHeaderText = 添加該列 DataGridViewColumnsInsert( _ DataGridViewColumnsCount Details)

   顯示了包含新列的網格以下代碼會對任何行中的按鈕單擊事件做出反應並顯示相應的記錄信息

  Private Sub DataGridView_CellClick( _ ByVal sender As SystemObject _ ByVal e As SystemWindowsForms _ DataGridViewCellEventArgs) _ Handles DataGridViewCellClick If DataGridViewColumns(eColumnIndex)Name = _ Details Then MessageBoxShow(You picked & _ DataGridViewRows(eRowIndex) _ Cells(CustomerID)Value) End If End Sub

  比較現實的方案是在此時創建並顯示一個新窗口並將有關選定記錄的信息傳遞到這個新窗口以便查詢並顯示完整的信息


圖像列

  datagridview 提供的另一種列是 DataGridViewImageColumn這種列將在單元格邊框內顯示一個圖片您可以設置 DataGridViewImageColumnLayout 屬性以便配置圖片在單元格中的顯示方式是將單元格擴展到適當的大小還是將直接剪裁太大的圖像

  使用 DataGridViewImageColumn 的方法有兩種首先您可以采用與 DataGridViewButtonColumn 相同的方式手動創建並添加該列如果您需要顯示 DataSet 本身不提供的相關圖像信息則此列非常有用例如您可能需要獲取文件名(如 ProductPicgif)從網絡驅動器讀取相應的文件然後在網格中顯示該文件為完成此操作您需要對 DataGridView 事件(如 CellFormatting)做出反應以便讀取相應行的圖片獲取圖像數據並使用該列中的 Value 屬性將其插入

  如果 DataSet 包含不需要任何手動操作的二進制圖片數據那麼事情會變得更加簡單例如 SQL Server Pubs 數據庫中的 pub_info 表該表包含公司徽標綁定至此表時您不需要執行任何額外步驟DataGridView 將自動識別出您正在使用圖像並會創建所需的 DataGridViewImageColumn(有關這項技術的示例請參閱本文的下載內容


編輯 DataGridView

  眾所周知datagrid 的用戶輸入功能很不靈活您幾乎沒有辦法自定義單元格驗證方式及錯誤報告方式而另一方面DataGridView 允許您通過對在編輯過程的所有階段中引發的大量不同事件做出反應來控制其行為

  默認情況下當用戶用鼠標雙擊單元格或按 F 鍵時DataGridView 單元格將進入編輯模式您還可以通過將 DataGridViewEditCellOnEnter 屬性設置為 True對 DataGridView 進行配置以便當用戶移到該單元格後該單元格立即切換到編輯模式您還可以使用 DataGridView 的 BeginEdit()CancelEdit()CommitEdit() 和 EndEdit() 方法通過編程方式開始和停止單元格編輯用戶編輯單元格時行標題將顯示一個鉛筆狀的編輯圖標

  用戶可以通過按 Esc 鍵來取消編輯如果將 EditCellOnEnter 屬性設置為 True則單元格仍將處於編輯模式但是所有更改都將被放棄要提交更改用戶只需移到新的單元格或將焦點切換到其他控件如果您的代碼可以移動當前單元格的位置則此代碼也會提交更改

  為防止單元格被編輯可以設置 DataGridViewCellDataGridViewColumnDataGridViewRow 或 DataGridView 的 ReadOnly 屬性(取決於您是要防止對該單元格進行更改對該列中的所有單元格進行更改對該行中的所有單元格進行更改還是要防止對該表中的所有單元格進行更改)DataGridView 還提供了 CellBeginEdit 事件用於取消嘗試的編輯


處理錯誤

  默認情況下datagridviewtextboxcolumn 允許用戶輸入任何字符包括當前單元格中可能不允許使用的那些字符例如用戶可以在數字字段中鍵入非數字字符也可以指定與 DataSet 中定義的 ForeignKeyConstraint 或 UniqueConstraint 沖突的值DataGridView 采用不同的方式來處理這些問題

   ?

  如果可以將編輯的值轉換為所需的數據類型(例如用戶在數字列中鍵入了文本)則用戶將不能提交更改或導航到其他行而必須取消更改或編輯值

?

  如果編輯的值與 DataSet 中的約束沖突則用戶通過導航到其他行或按 Enter 鍵提交更改後更改將被立即取消

  這些處理方式適用於大多數情況但是如果需要您也可以通過響應 DataGridViewDataError 事件來參與錯誤處理該事件是在 DataGridView 偵聽到來自數據源的錯誤時引發的

  驗證輸入

  驗證是一項與錯誤處理稍有不同的任務通過錯誤處理您可以處理由 DataSet 報告的問題而通過驗證您可以捕獲您自己定義的錯誤情況例如 DataSet 中允許的數據在應用程序中卻沒有意義

  當用戶通過導航到新的單元格提交更改時datagridview 控件將引發 CellValidating 和 CellValidated 事件這些事件之後是 RowValidating 和 RowValidated 事件您可以響應這些事件檢查用戶輸入的值是否正確並執行所需的任何後期處理如果值無效通常您會通過兩種方式來做出響應即取消更改和單元格導航(通過將 EventArgs 對象的 Cancel 屬性設置為 True)或者設置某種錯誤文本來提醒用戶可以將錯誤文本置於其他控件中也可以使用相應的 DataGridViewRow 和 DataGridViewCell 的 ErrorText 屬性在 DataGrid 中顯示錯誤文本

   ?

  設置 DataGridViewCellErrorText 時單元格中將顯示感歎號圖標將鼠標懸停在此圖標上將顯示錯誤消息

?

  設置 DataGridViewRowErrorText 時行左側的行標題中將顯示感歎號圖標將鼠標懸停在此圖標上將顯示錯誤消息

  通常您會結合使用這兩種屬性並設置行和單元格中的錯誤消息以下示例檢查 CompanyName 字段中太長的文本輸入如果發現有問題的值則會將錯誤符號(紅色的感歎號)添加到單元格中並顯示描述該問題的工具提示文本

  Private Sub DataGridView_CellValidating( _ ByVal sender As SystemObject _ ByVal e As SystemWindowsForms _ DataGridViewCellValidatingEventArgs) _ Handles DataGridViewCellValidating If DataGridViewColumns(eColumnIndex)Name = _ CompanyName Then If CType(eFormattedValue String)Length > _ Then DataGridViewRows( _ eRowIndex)Cells(eColumnIndex) _ ErrorText = _ The company name is too long End If End If End Sub


 
使用列表列約束選擇

  使用驗證可以捕獲任何錯誤情況但是這種方法不一定是最好的因為它允許用戶輸入無效的內容然後在事實出現後嘗試改正無效輸入更好的解決方案是使用戶在一開始就無法輸入任何無效的內容

  一個常見例子就是您需要將列限制在預定義值列表的范圍內在此示例中對於用戶而言最簡單的辦法是從列表中選擇正確的值而不要手動鍵入值最大的優勢在於您可以使用 DataGridViewComboBoxColumn 非常方便地實現此設計

  可以使用 Items 集合手動為 DataGridViewComboBoxColumn 添加項列表就像使用 ListBox 一樣此外還可以將 DataGridViewComboBoxColumn 綁定到其他數據源在這種情況下您可以使用 DataSource 屬性來指定數據源並使用 DisplayMember 屬性指示列中應顯示的值以及使用 ValueMember 屬性指定底層列值應使用的值

  為了演示這種情況來看看下一個有關 Products 表的示例此表中的每一條記錄都通過其 CategoryID 字段鏈接至 Categories 表中的記錄要更改產品類別用戶需要記住正確的 ID並將其輸入到 CategoryID 字段中更好的解決方案是使用與 Categories 表綁定的 DataGridViewComboBoxColumn此列將使用 CategoryName 作為顯示值但是會將 CategoryID 作為真正的底層值此列仍將通過 DataPropertyName 屬性與 Products 表綁定在一起這意味著當用戶從列表中選擇新的 Category 時產品記錄的 CategoryID 字段將自動更改

  以下是配置此表所需的代碼

   刪除自動生成的 CategoryID 列 DataGridViewColumnsRemove(CategoryID) 為 CategoryID 創建列表列 Dim List As New DataGridViewComboBoxColumn() ListDisplayIndex = ListHeaderText = Category 此列綁定至 ProductsCategoryID 字段 ListDataPropertyName = CategoryID 該列表將從 Categories 表獲得數據 ListDataSource = dsTables(Categories) ListDisplayMember = CategoryName ListValueMember = CategoryID 添加該列 DataGridViewColumnsAdd(List)

  小結

  本文概要介紹了最值得期待的 NET 新控件之一DataGridView與 DataGrid 不同的是DataGridView 適用於各種不同的現實情況——無論是要處理數據綁定和用戶編輯還是僅涉及靜態文本顯示都可以采用 DataGridView簡而言之本文讓您近距離了解了 NET Framework 提供的一體化數據解決方案以及 Windows 窗體開發人員升級至 NET 的最引人注目的原因之一

  有關 Visual Studio NET Developer 和 Pinnacle Publishing 的詳細信息請訪問它們的 Web 站點

  注意這不是 Microsoft Corporation 的 Web 站點Microsoft 對其內容不承擔任何責任

  本文轉載自 月份的 Visual Studio NET Developer除非另有說明否則版權所有 Pinnacle Publishing Inc保留所有權利Visual Studio NET Developer 是 Pinnacle Publishing Inc 獨立發行的刊物未經 Pinnacle Publishing Inc 事先同意不得以任何形式使用或復制本文的任何部分(評論文章中的簡短引用除外)如需與 Pinnacle Publishing Inc 聯系請致電


From:http://tw.wingwit.com/Article/program/net/201311/13846.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.