2021-05-12 14:32:11
C#開發WinForm之DataGridView開發詳解
前言
DataGridView是開發Winform的一個列表展示,類似於表格。學會下面的基本特徵用法,再輔以經驗,基本功能開發沒問題。
基本的資料渲染
根據提供的資料展示出效果。
提供給DataGridView資料來源有很多方式,大致有如下三種:
直接增加,每個單元格型別都是DataGridViewTextBoxCell
int index=this.dataGridView1.Rows.Add(); this.dataGridView1.Rows[index].Cells[0].Value = "1"; this.dataGridView1.Rows[index].Cells[1].Value = "2"; this.dataGridView1.Rows[index].Cells[2].Value = "3";
直接增加一行,在行上的每天單元格內新增資料,缺點是太單一
直接增加,但我們可以指定單元格型別
DataGridViewRow row = new DataGridViewRow(); DataGridViewTextBoxCell textboxcell = new DataGridViewTextBoxCell(); textboxcell.Value = "aaa"; row.Cells.Add(textboxcell); DataGridViewComboBoxCell comboxcell = new DataGridViewComboBoxCell(); row.Cells.Add(comboxcell); dataGridView1.Rows.Add(row);
可選的型別如下圖:
使用vo物件
上面2種都不是我想要的,因為列表展示的資料大部分情況下是複雜的後臺回傳的資料。所以我建議使用Vo。
新建InfoVo.cs類
public class InfoVo { /// <summary> /// /// </summary> public string uidItem { get; set; } /// <summary> /// /// </summary> public string uidItemRevision { get; set; } /// <summary> /// /// </summary> public string primaryTag { get; set; } }
構造一個List,將InfoVo放進List物件裡,然後將List物件賦值給dataGridView.DataSource即可。
在表單的Load事件裡新增如下程式碼
private void SearchInfo_Load(object sender, EventArgs e) { List<InfoVo> list = new List<InfoVo>(); list.Add(new InfoVo(){ uidItem="1", uidItemRevision ="1", primaryTag ="1"}); list.Add(new InfoVo(){ uidItem="2", uidItemRevision ="2", primaryTag ="2"}); dataGridView.AutoGenerateColumns = false; dataGridView.DataSource = null; dataGridView.DataSource = list; }
直接賦值dataGridView.DataSource = list即可。這裡的AutoGenerateColumns是禁止dataGridView自動根據vo屬性建立列。
在表單上選中DataGridView,在屬性面板裡點選Columns選項。如下圖
在開啟的面板裡,我們可以建立列。選擇是否可見,設定擡頭
DataPropertyName:指定列繫結的資料來源屬性欄位。
在DolumnType裡我們可以指定單元格型別,如下圖
比如下拉框,或者單元框。
至此,我們可以渲染出DataGridView元件裡,下面看一些屬性。
dataGridView
列寬自適應
foreach (DataGridViewColumn column in dataGridView.Columns) { column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; }
成員名稱 | 說明 |
---|---|
NotSet | 列的大小調整行為從DataGridView.AutoSizeColumnsMode 屬性繼承。 |
None | 列寬不會自動調整。 |
AllCells | 調整列寬,以適合該列中的所有單元格的內容,包括標題單元格。 |
AllCellsExceptHeader | 調整列寬,以適合該列中的所有單元格的內容,不包括標題單元格。 |
DisplayedCells | 調整列寬,以適合當前螢幕上顯示的行的列中的所有單元格的內容,包括標題單元格。 |
DisplayedCellsExceptHeader | 調整列寬,以適合當前螢幕上顯示的行的列中的所有單元格的內容,不包括標題單元格。 |
ColumnHeader | 調整列寬,以適合列標題單元格的內容。 |
Fill | 調整列寬,使所有列的寬度正好填充控制元件的顯示區域,只需要水平捲動保證列寬在DataGridViewColumn.MinimumWidth屬性值以上。相對列寬由相對DataGridViewColumn.FillWeight屬性值決定。 |
如果想讓列寬能按比例填充顯示區域則 column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
禁止縮放單元格大小
2個屬性
- AllowUserToResizeColumns:true:禁止縮放列
- AllowUserToResizeRows:true:禁止縮放行
使用者自定義列的順序
使用者可以拖動的方式排序列展示
AllowUserToOrderColumns:true
是否可以編輯單元格
- 表單的ReadOnly為false
- 在Columns彈出的列編輯視窗裡,選擇列的ReadOnly為false
- SelectionMode為RowReadSelect(這是預設值)
行頭,列頭不顯示
在屬性面板裡選中RowheadersVisible和ColumnHeadersVisible,置為false
列表顯示不完全,必需滑鼠移到元件上才能顯示的bug
將RowheadersVisible置為false即可。
行頭顯示行號
為RowStateChanged事件新增監聽,(在屬性面板右邊閃電圖示下找)。
private void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e) { //顯示在HeaderCell上 for (int i = 0; i < this.dataGridView1.Rows.Count; i++) { DataGridViewRow r = this.dataGridView1.Rows[i]; r.HeaderCell.Value = string.Format("{0}", i + 1); } this.dataGridView1.Refresh(); }
行號沒有完全顯示出來的解決辦法是將DataGridView的RowHeadersWidthSizeMode屬性設定為AutoSizeToAllHeaders、AutoSizeToDisplayedHeaders或者AutoSizeToFirstHeader。
禁止自動建立列
如果我們提供的vo物件,dataGrid會自動根據屬性建立列,這不是我想要的,我希望能控制顯示。如下設定即可
dataGridView.AutoGenerateColumns = false;
修改單元格型別
單元格可以顯示檔案,也可以顯示單元框,下拉框,圖片和超鏈拉。只要在編輯列視窗裡選擇ColumnType下拉框,選擇一下即可。當然選擇的不同,資料設定不同,比如
單選框DataGridViewCheckBoxColumn如下
下拉框DataGridViewComboBoxColumn
選中模式
可以指定選中是整個行被選中還是每個小單元格被選中
SelectionMode,全部可選如下
其它
當然還有其它,只要我們熟悉,在屬性面板上幾乎都能找到。
選中事件
CellClick是選中事件,不用它即可,不要用CellContentClick
,因為如果單元格無內容,這個CellContentClick
事件不會觸發。
取得當前單元格內容 :DataGridView1.CurrentCell.Value
取得當前單元格的列 Index:DataGridView1.CurrentCell.ColumnIndex
取得當前單元格的行 Index:DataGridView1.CurrentCell.RowIndex
取得當前行:dataGridView.CurrentRow;
獲得繫結的vo
:
DataGridViewRow dataGridViewRow = dataGridView.CurrentRow; InfoVo infoVo = dataGridViewRow.DataBoundItem as InfoVo ; infoVo .uidItemRevision ;
如果表格可編輯,那麼編輯完表格會同步更新DataBoundItem繫結的vo物件
遍歷列表裡所有單元格
foreach (DataGridViewRow item in dataGridView.Rows) { //item是每行的物件,cells是單元格集合 if (null != item.Cells[0].Value && (Boolean)item.Cells[0].Value) { item.Cells[0].Value.toString(); } }
使用 DataGridView.CurrentCellAddress 屬性(而不是直接存取單元格)來確定單元格所在的
行: DataGridView.CurrentCellAddress.Y
列: DataGridView.CurrentCellAddress.X 。
當前的單元格可以通過設定 DataGridView 物件的 CurrentCell 來改變。可以通過 CurrentCell 來設定
DataGridView 的啟用單元格。將 CurrentCell 設為 Nothing(null) 可以取消啟用的單元格。
DataGridView DataGridViewCheckBoxColumn編輯時實時觸發事件
正常響應CellValueChanged()事件時,當改變checkbox狀態時,只有當焦點離開該單元格時才能觸發CellValueChanged()事件,
如果要改變checkbox值時實時觸發CellValueChanged()事件,需要借用CurrentCellDirtyStateChanged()事件來提交未提交控制元件的更改。
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dataGridView1.IsCurrentCellDirty) { dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); } }
事實上,當呼叫dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);時,就提交了當前的修改,很多其它事件都會有響應,其中CellValueChanged就是其中之一。
這樣CellValueChanged()事件就可以隨著checkbox的值的改變實時觸發。
以全選/反選為例說明當DataGridViewCheckBoxColumn發生變化時怎麼處理全選/反選。
CheckBox有3種狀態:選中(CheckState.Checked)/取消(CheckState.Unchecked)/部分選中(CheckState.Indeterminate)
在winForm元件裡拖拽一個CheckBox命名為selectAllCheckBox,Text為全選,拖拽一個LinkLabel命名為revSelectLinkLbl,Text為反選。
//全選 private void selectAllCheckBox_CheckedChanged(object sender, EventArgs e) { CheckBox c = sender as CheckBox; if(c.CheckState == CheckState.Checked) { ChangeDataSourceChecked(true); } else if(c.CheckState == CheckState.Unchecked) { ChangeDataSourceChecked(false); } } private void ChangeDataSourceChecked(Boolean isSelected) { foreach (SavePlmBomResponseVo savePlmBomResponseVo in dataSource) { savePlmBomResponseVo.checkedC = isSelected; } dataGridView.DataSource = null; dataGridView.DataSource = dataSource; } /// <summary> /// 反選 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void revSelectLinkLbl_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (this.selectAllCheckBox.CheckState == CheckState.Checked) { this.selectAllCheckBox.CheckState = CheckState.Unchecked; } else if(this.selectAllCheckBox.CheckState == CheckState.Unchecked) { this.selectAllCheckBox.CheckState = CheckState.Checked; } else { //部分選中 foreach (SavePlmBomResponseVo savePlmBomResponseVo in dataSource) { if (savePlmBomResponseVo.checkedC) { savePlmBomResponseVo.checkedC = false; } else { savePlmBomResponseVo.checkedC = true; } } dataGridView.DataSource = null; dataGridView.DataSource = dataSource; } } /// <summary> /// 處理DataSource資料變化時,全選/反選選中狀態 /// </summary> private void calSelectAllCheckBoxState() { int selectedCount = 0; foreach (SavePlmBomResponseVo savePlmBomResponseVo in dataSource) { if (savePlmBomResponseVo.checkedC) { ++selectedCount; } } if (selectedCount == 0) { if(this.selectAllCheckBox.CheckState != CheckState.Unchecked) { this.selectAllCheckBox.CheckState = CheckState.Unchecked; } } else if (selectedCount == dataSource.Count) { if (this.selectAllCheckBox.CheckState != CheckState.Checked) { this.selectAllCheckBox.CheckState = CheckState.Checked; } } else { if (this.selectAllCheckBox.CheckState != CheckState.Indeterminate) { this.selectAllCheckBox.CheckState = CheckState.Indeterminate; } } } /// <summary> /// 提交修改狀態 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (this.dataGridView.IsCurrentCellDirty) { this.dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit); } } //行值變化 private void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) { calSelectAllCheckBoxState(); }
到此這篇關於C#開發WinForm之DataGridView開發詳解的文章就介紹到這了,更多相關C# DataGridView開發內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章