C#開發(fā)WinForm之DataGridView開發(fā)詳解
前言
DataGridView是開發(fā)Winform的一個(gè)列表展示,類似于表格。學(xué)會下面的基本特征用法,再輔以經(jīng)驗(yàn),基本功能開發(fā)沒問題。
基本的數(shù)據(jù)渲染
根據(jù)提供的數(shù)據(jù)展示出效果。
提供給DataGridView數(shù)據(jù)源有很多方式,大致有如下三種:
直接增加,每個(gè)單元格類型都是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";
直接增加一行,在行上的每天單元格內(nèi)添加數(shù)據(jù),缺點(diǎn)是太單一
直接增加,但我們可以指定單元格類型
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種都不是我想要的,因?yàn)榱斜碚故镜臄?shù)據(jù)大部分情況下是復(fù)雜的后臺回傳的數(shù)據(jù)。所以我建議使用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; }
}
構(gòu)造一個(gè)List,將InfoVo放進(jìn)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自動根據(jù)vo屬性創(chuàng)建列。
在窗體上選中DataGridView,在屬性面板里點(diǎn)擊Columns選項(xiàng)。如下圖

在打開的面板里,我們可以創(chuàng)建列。選擇是否可見,設(shè)置抬頭
DataPropertyName:指定列綁定的數(shù)據(jù)源屬性字段。
在DolumnType里我們可以指定單元格類型,如下圖

比如下拉框,或者單元框。
至此,我們可以渲染出DataGridView組件里,下面看一些屬性。
dataGridView
列寬自適應(yīng)
foreach (DataGridViewColumn column in dataGridView.Columns)
{
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
| 成員名稱 | 說明 |
|---|---|
| NotSet | 列的大小調(diào)整行為從DataGridView.AutoSizeColumnsMode 屬性繼承。 |
| None | 列寬不會自動調(diào)整。 |
| AllCells | 調(diào)整列寬,以適合該列中的所有單元格的內(nèi)容,包括標(biāo)題單元格。 |
| AllCellsExceptHeader | 調(diào)整列寬,以適合該列中的所有單元格的內(nèi)容,不包括標(biāo)題單元格。 |
| DisplayedCells | 調(diào)整列寬,以適合當(dāng)前屏幕上顯示的行的列中的所有單元格的內(nèi)容,包括標(biāo)題單元格。 |
| DisplayedCellsExceptHeader | 調(diào)整列寬,以適合當(dāng)前屏幕上顯示的行的列中的所有單元格的內(nèi)容,不包括標(biāo)題單元格。 |
| ColumnHeader | 調(diào)整列寬,以適合列標(biāo)題單元格的內(nèi)容。 |
| Fill | 調(diào)整列寬,使所有列的寬度正好填充控件的顯示區(qū)域,只需要水平滾動保證列寬在DataGridViewColumn.MinimumWidth屬性值以上。相對列寬由相對DataGridViewColumn.FillWeight屬性值決定。 |
如果想讓列寬能按比例填充顯示區(qū)域則 column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
禁止縮放單元格大小
2個(gè)屬性
- AllowUserToResizeColumns:true:禁止縮放列
- AllowUserToResizeRows:true:禁止縮放行
用戶自定義列的順序
用戶可以拖動的方式排序列展示
AllowUserToOrderColumns:true
是否可以編輯單元格
- 窗體的ReadOnly為false
- 在Columns彈出的列編輯窗口里,選擇列的ReadOnly為false
- SelectionMode為RowReadSelect(這是默認(rèn)值)
行頭,列頭不顯示
在屬性面板里選中RowheadersVisible和ColumnHeadersVisible,置為false
列表顯示不完全,必需鼠標(biāo)移到組件上才能顯示的bug
將RowheadersVisible置為false即可。
行頭顯示行號
為RowStateChanged事件添加監(jiān)聽,(在屬性面板右邊閃電圖標(biāo)下找)。
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屬性設(shè)置為AutoSizeToAllHeaders、AutoSizeToDisplayedHeaders或者AutoSizeToFirstHeader。
禁止自動創(chuàng)建列
如果我們提供的vo對象,dataGrid會自動根據(jù)屬性創(chuàng)建列,這不是我想要的,我希望能控制顯示。如下設(shè)置即可
dataGridView.AutoGenerateColumns = false;
修改單元格類型
單元格可以顯示文件,也可以顯示單元框,下拉框,圖片和超鏈拉。只要在編輯列窗口里選擇ColumnType下拉框,選擇一下即可。當(dāng)然選擇的不同,數(shù)據(jù)設(shè)置不同,比如
單選框DataGridViewCheckBoxColumn如下

下拉框DataGridViewComboBoxColumn

選中模式
可以指定選中是整個(gè)行被選中還是每個(gè)小單元格被選中
SelectionMode,全部可選如下

其它
當(dāng)然還有其它,只要我們熟悉,在屬性面板上幾乎都能找到。
選中事件
CellClick是選中事件,不用它即可,不要用CellContentClick,因?yàn)槿绻麊卧駸o內(nèi)容,這個(gè)CellContentClick事件不會觸發(fā)。
取得當(dāng)前單元格內(nèi)容 :DataGridView1.CurrentCell.Value
取得當(dāng)前單元格的列 Index:DataGridView1.CurrentCell.ColumnIndex
取得當(dāng)前單元格的行 Index:DataGridView1.CurrentCell.RowIndex
取得當(dāng)前行: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 。
當(dāng)前的單元格可以通過設(shè)定 DataGridView 對象的 CurrentCell 來改變??梢酝ㄟ^ CurrentCell 來設(shè)定
DataGridView 的激活單元格。將 CurrentCell 設(shè)為 Nothing(null) 可以取消激活的單元格。
DataGridView DataGridViewCheckBoxColumn編輯時(shí)實(shí)時(shí)觸發(fā)事件
正常響應(yīng)CellValueChanged()事件時(shí),當(dāng)改變checkbox狀態(tài)時(shí),只有當(dāng)焦點(diǎn)離開該單元格時(shí)才能觸發(fā)CellValueChanged()事件,
如果要改變checkbox值時(shí)實(shí)時(shí)觸發(fā)CellValueChanged()事件,需要借用CurrentCellDirtyStateChanged()事件來提交未提交控件的更改。
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
事實(shí)上,當(dāng)調(diào)用dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);時(shí),就提交了當(dāng)前的修改,很多其它事件都會有響應(yīng),其中CellValueChanged就是其中之一。
這樣CellValueChanged()事件就可以隨著checkbox的值的改變實(shí)時(shí)觸發(fā)。
以全選/反選為例說明當(dāng)DataGridViewCheckBoxColumn發(fā)生變化時(shí)怎么處理全選/反選。
CheckBox有3種狀態(tài):選中(CheckState.Checked)/取消(CheckState.Unchecked)/部分選中(CheckState.Indeterminate)
在winForm組件里拖拽一個(gè)CheckBox命名為selectAllCheckBox,Text為全選,拖拽一個(gè)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數(shù)據(jù)變化時(shí),全選/反選選中狀態(tài)
/// </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>
/// 提交修改狀態(tài)
/// </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();
}
到此這篇關(guān)于C#開發(fā)WinForm之DataGridView開發(fā)詳解的文章就介紹到這了,更多相關(guān)C# DataGridView開發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c# WPF中System.Windows.Interactivity的使用
這篇文章主要介紹了c# WPF中System.Windows.Interactivity的使用,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03
C#使用SignalR實(shí)現(xiàn)與前端vue實(shí)時(shí)通信的示例代碼
SignalR 是 ASP.NET Core 的一個(gè)庫,它簡化了在應(yīng)用程序中添加實(shí)時(shí)通信的過程,無論是聊天應(yīng)用、實(shí)時(shí)游戲還是協(xié)作工具,SignalR 都能提供高效且易于實(shí)現(xiàn)的解決方案,本文給大家介紹了C#使用SignalR實(shí)現(xiàn)與前端vue實(shí)時(shí)通信的實(shí)現(xiàn),需要的朋友可以參考下2024-10-10
C# WinForm應(yīng)用程序降低系統(tǒng)內(nèi)存占用方法總結(jié)
這篇文章主要介紹了C# WinForm應(yīng)用程序降低系統(tǒng)內(nèi)存占用方法總結(jié),本文總結(jié)了9個(gè)方法,同時(shí)給出了一個(gè)定期清理執(zhí)行垃圾回收代碼,需要的朋友可以參考下2014-10-10
C#中Thread(線程)和Task(任務(wù))實(shí)例詳解
.NET Framework在System.Threading命名空間中具有與線程相關(guān)的類,線程是一小組可執(zhí)行指令,這篇文章主要給大家介紹了關(guān)于C#中Thread(線程)和Task(任務(wù))的相關(guān)資料,需要的朋友可以參考下2022-03-03

