C# Winform DataGridView數(shù)據(jù)刷新問題的解決辦法
一、問題
DataGridView 是比較常用的表格控件,在 DataGridView 中顯示數(shù)據(jù), 一般使用 dataGridView1.DataSource = 數(shù)據(jù)源,來綁定數(shù)據(jù),數(shù)據(jù)源可以是 DataTable、List、Dictionary 等,那么如何做到及時刷新數(shù)據(jù)呢,這里我提出幾個問題:
1.綁定一個空的數(shù)據(jù)源,后面向數(shù)據(jù)源添加數(shù)據(jù)。
2.DataGridView 綁定一個有數(shù)據(jù)的數(shù)據(jù)源,后面再向數(shù)據(jù)源添加數(shù)據(jù)。
3.將數(shù)據(jù)源的某一行,某一列的數(shù)據(jù)修改為其他的數(shù)據(jù)。
4.刪除數(shù)據(jù)源的某一列。
做了上面的操作,DataGridView 控件會有怎樣的效果?
二、創(chuàng)建項目
新建一個 winform 項目,界面如下:

為了能隨機的生產(chǎn)用戶名,我特意的加了一個類 GetNameHelper,這個類的代碼是從是網(wǎng)上復(fù)制的。
using System;
using System.Collections.Generic;
/// <summary>
/// 生成隨機姓名
/// </summary>
public class GetNameHelper
{
/// <summary>
/// 姓
/// </summary>
private static List<string> SurnameList = new List<string>() {"趙", "錢", "孫", "李", "周", "吳", "鄭", "王", "馮", "陳", "楮", "衛(wèi)", "蔣", "沈", "韓", "楊",
"朱", "秦", "尤", "許", "何", "呂", "施", "張", "孔", "曹", "嚴", "華", "金", "魏", "陶", "姜",
"戚", "謝", "鄒", "喻", "柏", "水", "竇", "章", "云", "蘇", "潘", "葛", "奚", "范", "彭", "郎",
"魯", "韋", "昌", "馬", "苗", "鳳", "花", "方", "俞", "任", "袁", "柳", "酆", "鮑", "史", "唐",
"費", "廉", "岑", "薛", "雷", "賀", "倪", "湯", "滕", "殷", "羅", "畢", "郝", "鄔", "安", "常",
"樂", "于", "時", "傅", "皮", "卞", "齊", "康", "伍", "余", "元", "卜", "顧", "孟", "平", "黃",
"和", "穆", "蕭", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "貝", "明", "臧",
"計", "伏", "成", "戴", "談", "宋", "茅", "龐", "熊", "紀", "舒", "屈", "項", "祝", "董", "梁",
"杜", "阮", "藍", "閩", "席", "季", "麻", "強", "賈", "路", "婁", "危", "江", "童", "顏", "郭",
"梅", "盛", "林", "刁", "鍾", "徐", "丘", "駱", "高", "夏", "蔡", "田", "樊", "胡", "凌", "霍",
"虞", "萬", "支", "柯", "昝", "管", "盧", "莫", "經(jīng)", "房", "裘", "繆", "干", "解", "應(yīng)", "宗",
"丁", "宣", "賁", "鄧", "郁", "單", "杭", "洪", "包", "諸", "左", "石", "崔", "吉", "鈕", "龔",
"程", "嵇", "邢", "滑", "裴", "陸", "榮", "翁", "荀", "羊", "於", "惠", "甄", "麹", "家", "封",
"芮", "羿", "儲", "靳", "汲", "邴", "糜", "松", "井", "段", "富", "巫", "烏", "焦", "巴", "弓",
"牧", "隗", "山", "谷", "車", "侯", "宓", "蓬", "全", "郗", "班", "仰", "秋", "仲", "伊", "宮",
"寧", "仇", "欒", "暴", "甘", "斜", "厲", "戎", "祖", "武", "符", "劉", "景", "詹", "束", "龍",
"葉", "幸", "司", "韶", "郜", "黎", "薊", "薄", "印", "宿", "白", "懷", "蒲", "邰", "從", "鄂",
"索", "咸", "籍", "賴", "卓", "藺", "屠", "蒙", "池", "喬", "陰", "郁", "胥", "能", "蒼", "雙",
"聞", "莘", "黨", "翟", "譚", "貢", "勞", "逄", "姬", "申", "扶", "堵", "冉", "宰", "酈", "雍",
"郤", "璩", "桑", "桂", "濮", "牛", "壽", "通", "邊", "扈", "燕", "冀", "郟", "浦", "尚", "農(nóng)",
"溫", "別", "莊", "晏", "柴", "瞿", "閻", "充", "慕", "連", "茹", "習", "宦", "艾", "魚", "容",
"向", "古", "易", "慎", "戈", "廖", "庾", "終", "暨", "居", "衡", "步", "都", "耿", "滿", "弘",
"匡", "國", "文", "寇", "廣", "祿", "闕", "東", "歐", "殳", "沃", "利", "蔚", "越", "夔", "隆",
"師", "鞏", "厙", "聶", "晁", "勾", "敖", "融", "冷", "訾", "辛", "闞", "那", "簡", "饒", "空",
"曾", "毋", "沙", "乜", "養(yǎng)", "鞠", "須", "豐", "巢", "關(guān)", "蒯", "相", "查", "后", "荊", "紅",
"游", "竺", "權(quán)", "逑", "蓋", "益", "桓", "公", "仉", "督", "晉", "楚", "閻", "法", "汝", "鄢",
"涂", "欽", "岳", "帥", "緱", "亢", "況", "后", "有", "琴", "歸", "海", "墨", "哈", "譙", "笪",
"年", "愛", "陽", "佟", "商", "牟", "佘", "佴", "伯", "賞",
"萬俟", "司馬", "上官", "歐陽", "夏侯", "諸葛", "聞人", "東方", "赫連", "皇甫", "尉遲", "公羊",
"澹臺", "公冶", "宗政", "濮陽", "淳于", "單于", "太叔", "申屠", "公孫", "仲孫", "軒轅", "令狐",
"鍾離", "宇文", "長孫", "慕容", "鮮于", "閭丘", "司徒", "司空", "丌官", "司寇", "子車", "微生",
"顓孫", "端木", "巫馬", "公西", "漆雕", "樂正", "壤駟", "公良", "拓拔", "夾谷", "宰父", "谷梁",
"段干", "百里", "東郭", "南門", "呼延", "羊舌", "梁丘", "左丘", "東門", "西門", "南宮"};
/// <summary>
/// 男性 名
/// </summary>
private static string LastNameMan = "剛偉勇毅俊峰強軍平保東文輝力明永健世廣志義興良海山仁波寧貴福生龍元全國勝學祥才發(fā)武新利清飛彬富順信子杰濤昌成康星光天達安巖中茂進林有堅和彪博誠先敬震振壯會思群豪心邦承樂紹功松善厚慶磊民友裕河哲江超浩亮政謙亨奇固之輪翰朗伯宏言若鳴朋斌梁棟維啟克倫翔旭鵬澤晨辰士以建家致樹炎德行時泰盛雄琛鈞冠策騰楠榕風航弘";
/// <summary>
/// 女性 名
/// </summary>
private static string LastNameWoMan = "秀娟英華慧巧美娜靜淑惠珠翠雅芝玉萍紅娥玲芬芳燕彩春菊蘭鳳潔梅琳素云蓮真環(huán)雪榮愛妹霞香月鶯媛艷瑞凡佳嘉瓊勤珍貞莉桂娣葉璧璐婭琦晶妍茜秋珊莎錦黛青倩婷姣婉嫻瑾穎露瑤怡嬋雁蓓紈儀荷丹蓉眉君琴蕊薇菁夢嵐苑婕馨瑗琰韻融園藝詠卿聰瀾純毓悅昭冰爽琬茗羽希寧欣飄育瀅馥筠柔竹靄凝魚曉歡霄楓蕓菲寒伊亞宜可姬舒影荔枝思麗墨";
private static Random random = new Random();
/// <summary>
/// 隨機取一個姓
/// </summary>
/// <returns></returns>
private static string GetSurname()
{
return SurnameList[random.Next(0, SurnameList.Count)];
}
/// <summary>
/// 隨機取一個名
/// </summary>
/// <param name="sex">1:男/2:女</param>
/// <returns></returns>
private static string GetName(int sex)
{
//名 長度 ,1個或者2個字
var nameLen = random.Next(1, 3);
var name = "";
for (int i = 0; i < nameLen; i++)
{
if (sex == 1) name += LastNameMan[random.Next(0, LastNameMan.Length)];
else name += LastNameWoMan[random.Next(0, LastNameWoMan.Length)];
}
return name;
}
/// <summary>
/// 隨機生成一個男性姓名
/// </summary>
/// <returns></returns>
public static string GetManName()
{
return GetSurname() + GetName(1);
}
/// <summary>
/// 隨機生成一個女性姓名
/// </summary>
/// <returns></returns>
public static string GetWomanName()
{
return GetSurname() + GetName(2);
}
/// <summary>
/// 隨機生產(chǎn)一個名字,隨機性別
/// </summary>
/// <returns></returns>
public static string GetRandomName()
{
int sex = random.Next(1, 3);
if (sex == 1)
return GetManName();
else if (sex == 2)
return GetWomanName();
else
return "未知";
}
}接著,給 Form1 添加代碼,用來測試增刪改查等操作。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 數(shù)據(jù)綁定
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<data> dataList = new List<data>();
private Random Random = new Random();
//綁定數(shù)據(jù)
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = dataList;
Console.WriteLine("綁定數(shù)據(jù)");
}
//添加數(shù)據(jù)
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)
{
data datas = new data();
datas.name = GetNameHelper.GetRandomName();
datas.age = Random.Next(1, 100);
datas.height = Random.Next(150, 200);
dataList.Add(datas);
}
Console.WriteLine("添加數(shù)據(jù),現(xiàn)在 list 的長度:{0}", dataList.Count);
}
//刷新數(shù)據(jù)
private void button3_Click(object sender, EventArgs e)
{
dataGridView1.Invalidate();
Console.WriteLine("刷新數(shù)據(jù)");
}
//更新數(shù)據(jù)
private void button4_Click(object sender, EventArgs e)
{
if(dataList.Count > 0)
{
dataList[0].name = GetNameHelper.GetRandomName();
dataList[0].height = Random.Next(150, 200);
dataList[0].age = Random.Next(1, 100);
Console.WriteLine("更新數(shù)據(jù)");
}
}
}
}
public class data
{
public string name { get; set; }
public int age { get; set; }
public int height { get; set; }
}三、綁定空的數(shù)據(jù)源
將一個空的 List 綁定到 dataGridView1,后面再添加數(shù)據(jù)
效果:

從上面的動圖可以看到,在 DataGridView 綁定空的 List 后,給 List 添加數(shù)據(jù),包括給 DataGridView 刷新表格,給 List 修改數(shù)據(jù),都沒有效果,DataGridView 界面沒有任何變化。
控制臺的輸出:

四、綁定有數(shù)據(jù)的數(shù)據(jù)源
現(xiàn)在測試第2個問題,綁定一個有數(shù)據(jù)的數(shù)據(jù)源,能否直接顯示出來呢?

控制臺的輸出:

在添加數(shù)據(jù)后,在綁定 DataGridView 確實能顯示對應(yīng)的數(shù)據(jù),但是在綁定后,如果再次添加其他數(shù)據(jù),也會和上節(jié)一樣,不會再有其他的變化,即使刷新表單也是一樣。
五、修改綁定的數(shù)據(jù)源
第四個按鈕,可以修改數(shù)據(jù)源的數(shù)據(jù),用第三個按鈕進行刷新,DataGridView 控件刷新界面的的方法是 Invalidate ,在上面幾節(jié)的測試中,都有用過。

控制臺的輸出:

在上面的幾個測試中,測試了綁定數(shù)據(jù)源的幾種情況,在 List 的長度增加, DataGridView 刷新表格,并沒有什么作用,那么要如何解決這個問題呢?
六、解決數(shù)據(jù)源刷新問題
解決數(shù)據(jù)源刷新問題也很簡單,設(shè)置 dataGridView1.DataSource = null; 然后重新綁定就可以了,下面是完整的代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 數(shù)據(jù)綁定
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<data> dataList = new List<data>();
private Random Random = new Random();
//綁定數(shù)據(jù)
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = dataList;
Console.WriteLine("綁定數(shù)據(jù)");
}
//添加數(shù)據(jù)
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)
{
data datas = new data();
datas.name = GetNameHelper.GetRandomName();
datas.age = Random.Next(1, 100);
datas.height = Random.Next(150, 200);
dataList.Add(datas);
}
Console.WriteLine("添加數(shù)據(jù),現(xiàn)在 list 的長度:{0}", dataList.Count);
}
//刷新數(shù)據(jù)
private void button3_Click(object sender, EventArgs e)
{
Console.WriteLine("刷新數(shù)據(jù)");
if (dataList.Count == 0)
{
dataGridView1.DataSource = null;
return;
}
if (dataGridView1.DataSource != null)
{
if (dataList.Count != dataGridView1.Rows.Count)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = dataList;
return;
}
dataGridView1.Invalidate();
return;
}
if (dataGridView1.DataSource == null)
dataGridView1.DataSource = dataList;
}
//更新數(shù)據(jù)
private void button4_Click(object sender, EventArgs e)
{
if(dataList.Count > 0)
{
dataList[0].name = GetNameHelper.GetRandomName();
dataList[0].height = Random.Next(150, 200);
dataList[0].age = Random.Next(1, 100);
Console.WriteLine("更新數(shù)據(jù)");
}
}
}
}
public class data
{
public string name { get; set; }
public int age { get; set; }
public int height { get; set; }
}測試:

控制臺輸出:

上面這種寫法,雖然看起來沒問題,但是,如果移除綁定的 List 最后一個元素,可能會出現(xiàn)問題,會報下面的錯誤:

或者

這個錯誤我也不知道是什么原因?qū)е碌?,我關(guān)閉 Visual Studio 后重新打開,又發(fā)現(xiàn)是正常的,后面我把代碼改為在 Form1_Load 中進行綁定
private void Form1_Load(object sender, EventArgs e)
{
//設(shè)置焦點,不讓輸入框一打開就聚焦
this.ActiveControl = this.label1;
dataGridView1.DataSource = dataList;
}然后使用定時器調(diào)用 UpdateDataTable 方法來刷新數(shù)據(jù),就再也沒有這個錯誤了
private void UpdateDataTable()
{
if (dataGridView1.DataSource != null)
{
if (UserList.Count != dataGridView1.Rows.Count)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = UserList;
return;
}
dataGridView1.Invalidate();
}
}但是又出現(xiàn)了一個新的錯誤,由于綁定了一個空的 List,運行時候點擊 dataGridView1 表單,就會報下面的錯誤

所以,還是用下面的代碼吧,我稍微做了下封裝
/// <summary>
/// 刷新表格
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
private void UpdateDataTable<T>(List<T> list)
{
if (list.Count == 0)
{
dataGridView1.DataSource = null;
return;
}
if (dataGridView1.DataSource == null)
{
dataGridView1.DataSource = list;
}
else
{
if (dataGridView1.Rows.Count != list.Count)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = list;
return;
}
dataGridView1.Invalidate();
}
}如果需要調(diào)整列的寬度,可以這么寫
/// <summary>
/// 刷新表格
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
private void UpdateDataTable<T>(List<T> list)
{
if (list.Count == 0)
{
dataGridView1.DataSource = null;
return;
}
if (dataGridView1.DataSource == null)
{
dataGridView1.DataSource = list;
DataGridView1Resize();
}
else
{
if (dataGridView1.Rows.Count != list.Count)
{
dataGridView1.DataSource = null;
dataGridView1.DataSource = list;
DataGridView1Resize();
return;
}
dataGridView1.Invalidate();
}
}
/// <summary>
/// 調(diào)整 DataGridView1 的表格寬度
/// </summary>
private void DataGridView1Resize()
{
//根據(jù)實際情況來寫
dataGridView1.Columns[0].Width = 130;
dataGridView1.Columns[1].Width = 80;
dataGridView1.Columns[2].Width = 80;
}另外,dataGridView 經(jīng)常刷新數(shù)據(jù),會有界面閃爍的問題,下面解決界面閃爍。
七、解決刷新數(shù)據(jù)界面閃爍
添加一個類 DoubleBufferDataGridView
using System;
using System.Reflection;
using System.Windows.Forms;
public static class DoubleBufferDataGridView
{
/// <summary>
/// 雙緩沖,解決閃爍問題
/// </summary>
public static void DoubleBufferedDataGirdView(this DataGridView dgv, bool flag)
{
Type dgvType = dgv.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(dgv, flag, null);
}
}在 Form1 代碼中,綁定對應(yīng)的 DataGridView 就行了,比如,我有三個 DataGridView,那么就綁定三個
public Form1()
{
InitializeComponent();
//解決界面數(shù)據(jù)刷新時閃爍的問題
dataGridView1.DoubleBufferedDataGirdView(true);
dataGridView2.DoubleBufferedDataGirdView(true);
dataGridView3.DoubleBufferedDataGirdView(true);
}這樣:

其實只要你不經(jīng)常將 dataGridView1.DataSource = null; 然后重新綁定數(shù)據(jù)源,界面閃爍問題,還是可以接受的。
以上就是C# Winform DataGridView數(shù)據(jù)刷新問題的解決辦法的詳細內(nèi)容,更多關(guān)于C# Winform DataGridView數(shù)據(jù)刷新的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c#實現(xiàn)多線程局域網(wǎng)聊天系統(tǒng)
這篇文章主要介紹了c#實現(xiàn)多線程局域網(wǎng)聊天系統(tǒng)的相關(guān)代碼,有此方面需求的小伙伴可以參考下。2015-06-06
C# 4.0 大數(shù)的運算--BigInteger的應(yīng)用詳解
本篇文章是對C# 4.0 大數(shù)的運算 BigInteger的應(yīng)用進行了詳細的分析介紹,需要的朋友參考下2013-05-05
淺析C#靜態(tài)類,靜態(tài)構(gòu)造函數(shù),靜態(tài)變量
這篇文章主要介紹了淺析C#靜態(tài)類,靜態(tài)構(gòu)造函數(shù),靜態(tài)變量 的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-06-06

