c#学习笔记-----Listview 、dataGridView 控件
1 概述
listView和dataGridView是c#显示控件中比较复杂的控件,(还有一个treeView也比较复杂,但是在此没有太大的关联性)当需要显示大量的数据时候,一些box控件已经不能满足需要了。在大量数据显示时,至于什么时候使用listView(一般数据保存在内存中),什么时候使用使用dataGridView(一般数据保存在数据库中)就要看需求了。其实listView和dataGridView有很多相同的地方,可以说掌握了其中一个,另一个也就差不多了。正如开头所说这2个控件使用起来并不简单,主要的难点是过于庞杂的属性和方法列表,过于繁杂的事件,让初学者晕头转向不知道该从何处下手,所以一个好的学习路线是非常必要的。鉴于控件的复杂性本篇笔记借鉴peterzb的路线,部分代码也有所借鉴,此处附上原文链接:http://www.cnblogs.com/peterzb/archive/2009/05/29/1491891.html。想要深入研究,可以去看原文。
fhbds!
2 ListView
先看一下我实现的效果吧!
2.1 listView视图
listView视图一共有5种视图,包括Details、LargeIcon、List、SmallIcon、Tile(默认为 LargeIcon),因为默认是LargeIcon视图,所以一般刚开始的新手很难做到上面这种列表的显示方式。此处也只介绍Details(上面实现的方式),其它视图不太适合显示数据,倒是适合显示图片,此时并不感兴趣!接下来讲一下我实现的路线,如果自己没有路线的可以跟着一起做,只附上主要代码,需要全部的请留下QQ邮箱!
为了避免listView在更新数据的时候有闪烁现象,不使用System.Windows.Forms.ListView 而是自定义一个子类去继承它。
1 class ListViewNF : System.Windows.Forms.ListView 2 { 3 public ListViewNF()//避免闪烁 4 { 5 6 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 7 8 9 this.SetStyle(ControlStyles.EnableNotifyMessage, true); 10 } 11 12 protected override void OnNotifyMessage(Message m) 13 { 14 15 if (m.Msg != 0x14) 16 { 17 base.OnNotifyMessage(m); 18 } 19 } 20 }
接下来创建一个listView1,此时需要到Form1.designer.cs做以下修改: this.listView1 = new show.ListViewNF();
private ListViewNF listView1;
原本这两句是this.listView1=new System.Windows.Forms.ListView1();建好之后,可以按照上面把页面的一些button和textBox建好,接下来就一一实现即可。
首先需要实现窗体加载事件,一开始就把listView的一些属性确立下来,各属性已在注释中说明。
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 listView1.View = View.Details;//设置视图 获取或设置项在控件中的显示方式 4 listView1.FullRowSelect = true;//设置是否行选择模式 5 listView1.GridLines = true;//设置网格线 6 listView1.AllowColumnReorder = true;//设置是否可拖动列标头来对改变列的顺序。 7 listView1.MultiSelect = true;//设置是否可以选择多个项 8 listView1.LabelEdit = true;//设置用户是否可以编辑控件中项的标签,对于Detail视图,只能编辑行第一列的内容 9 listView1.CheckBoxes = true;//设置控件中各项的旁边是否显示复选框 10 11 12 listView1.SmallImageList = imageList1;//设置图标 13 14 //添加列 15 listView1.Columns.Add("序号", 100, HorizontalAlignment.Left); 16 listView1.Columns.Add("商品名称", 150, HorizontalAlignment.Left); 17 listView1.Columns.Add("商品数量", 150, HorizontalAlignment.Left); 18 listView1.Columns.Add("商品单价", 80, HorizontalAlignment.Left); 19 listView1.Columns.Add("商品产地", 80, HorizontalAlignment.Left); 20 29 30 listView1.BeginUpdate(); 33 listView1.EndUpdate(); 34 }
Details视图可以在第一列显示图标,想要加入图标的可以创建一个imageList控件,加入图片方式如下:
listView通过index和图片绑定,需要预先设置几个全局变量,后面要用到连接数据库,所以一并全部加上。
1 public int count = 0; 2 public int pictureCount = 0; 3 4 public static string dataSource = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=2013-20130829TH)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=oracle)));"; 5 public static string persistSecurityInfo = "Persist Security Info=True;"; 6 public static string userID = "User ID=SYSTEM;"; 7 public static string password = "Password=admin;"; 8 public static string connectionString = dataSource + persistSecurityInfo + userID + password;
实现添加记录:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 // ListViewItem Item = new ListViewItem(); 4 //Item.SubItems.Clear(); 5 6 //添加行 7 var item = new ListViewItem(); 8 item.SubItems.Clear(); 9 if (pictureCount>=imageList1.Images.Count-1) { 10 pictureCount = 0; 11 } 12 pictureCount++; 13 item.ImageIndex = pictureCount; 14 count++; 15 item.Text = count.ToString(); //序号 16 17 if (count % 3 == 0) 18 { 19 item.SubItems.Add("西瓜"); //商品名称 20 item.SubItems.Add("23"); //商品数量 21 item.SubItems.Add("1129"); //商品单价 22 item.SubItems.Add("巴西"); //商品产地 23 } 24 else if (count % 3 == 1) 25 { 26 item.SubItems.Add("苹果"); //商品名称 27 item.SubItems.Add("56"); //商品数量 28 item.SubItems.Add("9"); //商品单价 29 item.SubItems.Add("美国"); 30 } 31 else { 32 item.SubItems.Add("玉米"); //商品名称 33 item.SubItems.Add("6"); //商品数量 34 item.SubItems.Add("9999"); //商品单价 35 item.SubItems.Add("中国"); 36 } 37 38 39 40 listView1.BeginUpdate(); 41 listView1.Items.Add(item); 42 listView1.Items[listView1.Items.Count - 1].EnsureVisible();//滚动到最后 43 listView1.EndUpdate(); 44 item.EnsureVisible(); //关键的实现函数 45 }
清空:
1 private void button2_Click(object sender, EventArgs e) 2 { 3 // this.listView1.Clear(); //从控件中移除所有项和列(包括列表头)。 4 count = 0; 5 this.listView1.Items.Clear(); //只移除所有的项。 6 }
定位到第n行:
1 private void button3_Click(object sender, EventArgs e) 2 { 3 int i = 1; 4 if(textBox1.Text.Trim()==string.Empty ){ 5 i = 1; 6 } 7 try{ 8 i= Convert.ToInt32(textBox1.Text.Trim()); 9 }catch(Exception ex){ 10 i = 1; 11 MessageBox.Show(ex.Message); 12 } 13 14 if(i<=0 || i>=count){ 15 i = count; 16 } 17 18 listView1.EnsureVisible(i - 1); 19 }
查找:
1 private void button4_Click(object sender, EventArgs e) 2 { 3 ListViewItem foundItem = this.listView1.FindItemWithText(this.textBox2.Text.Trim(), true, 0); //参数1:要查找的文本;参数2:是否子项也要查找;参数3:开始查找位置 4 5 if (foundItem != null) 6 { 7 8 this.listView1.TopItem = foundItem; //定位到该项 9 10 //foundItem.ForeColor = Color.Red; 11 foundItem.BackColor = Color.Lime;//背景色 12 } 13 }
选中移除:
1 private void button7_Click(object sender, EventArgs e) 2 { 3 4 foreach (ListViewItem lvi in listView1.SelectedItems) //选中项遍历 5 { 6 //listView1.Items.RemoveAt(lvi.Index); // 按索引移除 7 listView1.Items.Remove(lvi); //按项移除 8 } 9 }
获取勾选中的:
1 private void button6_Click(object sender, EventArgs e) 2 { 3 int k = 0; 4 int m = listView1.CheckedItems.Count; 5 string[] a = new string[m]; 6 Queue<string> Q = new Queue<string>(); 7 8 for (int i = 0; i < m; i++) 9 { 10 if (listView1.CheckedItems[i].Checked) 11 { 12 Q.Enqueue(listView1.CheckedItems[i].SubItems[1].Text);//获取勾选的第二个栏位 13 } 14 } 15 while (Q.Count > 0) 16 { 17 a[k] = Q.Dequeue(); 18 k++; 19 } 20 21 foreach (var i in a) 22 { 23 textBox3.Text += i.ToString(); 24 } 25 }
获取点击选中的:
1 private void button8_Click(object sender, EventArgs e) 2 { 3 ListView.SelectedListViewItemCollection svc =this.listView1.SelectedItems; 4 5 6 foreach (ListViewItem item in svc) 7 { 8 textBox3.Text = item.SubItems[1].Text;//获取选中的第二个栏位 9 10 } 11 }
实现点击表头可以排序,首先需要自己构造一个排序器,其次要实现一个点击表头事件:
1 class ListViewSort : IComparer 2 { 3 private readonly int _col; 4 private readonly bool _descK; 5 6 public ListViewSort() 7 { 8 _col = 0; 9 } 10 11 public ListViewSort(int column, object desc) 12 { 13 _descK = (bool)desc; 14 _col = column; //当前列,0,1,2...,参数由ListView控件的ColumnClick事件传递 15 } 16 17 public int Compare(object x, object y) 18 { 19 int tempInt = String.CompareOrdinal(((ListViewItem)x).SubItems[_col].Text,((ListViewItem)y).SubItems[_col].Text); 20 if (_descK) 21 { 22 return -tempInt; 23 } 24 return tempInt; 25 } 26 27 }
1 private void listView1_ColumnClick(object sender, ColumnClickEventArgs e) 2 { 3 if (listView1.Columns[e.Column].Tag == null) 4 { 5 listView1.Columns[e.Column].Tag = true; 6 } 7 var tabK = (bool)listView1.Columns[e.Column].Tag; 8 listView1.Columns[e.Column].Tag = !tabK; 9 listView1.ListViewItemSorter = new ListViewSort(e.Column, listView1.Columns[e.Column].Tag); 10 //指定排序器并传送列索引与升序降序关键字 11 listView1.Sort();//对列表进行自定义排序 12 }
从数据库获取数据需要有一些执行sql的方法,可以参考我另外一篇笔记,此处的方法直接拿来用:
1 public static OracleDataReader ExecuteReader(string connectionString, string strsql) 2 { 3 OracleConnection conn = new OracleConnection(connectionString); 4 conn.Open(); 5 OracleCommand cmd = new OracleCommand(strsql, conn); 6 try 7 { 8 //CommandBehavior是一个枚举类型 9 OracleDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection); 10 11 return rdr; 12 } 13 catch 14 { 15 conn.Close(); 16 throw; 17 } 18 } 19 20 21 private void button5_Click(object sender, EventArgs e) 22 { 23 if (pictureCount >= imageList1.Images.Count - 1) 24 { 25 pictureCount = 0; 26 } 27 28 try 29 { 30 string sql1 = @"select * from goods"; 31 OracleDataReader odr = ExecuteReader(connectionString, sql1); 32 while(odr.Read()){ 33 var lvi = new ListViewItem(odr[0].ToString()); 34 35 if (pictureCount >= imageList1.Images.Count - 1) 36 { 37 pictureCount = 0; 38 } 39 lvi.ImageIndex = pictureCount; 40 pictureCount++; 41 42 lvi.SubItems.Add(odr[1].ToString()); 43 lvi.SubItems.Add(odr[2].ToString()); 44 lvi.SubItems.Add(odr[3].ToString()); 45 lvi.SubItems.Add(odr[4].ToString()); 46 47 listView1.BeginUpdate(); 48 this.listView1.Items.Add(lvi); 49 listView1.Items[listView1.Items.Count - 1].EnsureVisible();//滚动到最后 50 listView1.EndUpdate(); 51 lvi.EnsureVisible(); //关键的实现函数 52 } 53 odr.Close(); 54 } 55 catch (Exception ex) 56 { 57 MessageBox.Show(ex.Message); 58 } 59 }
效果如下:
3 dataGridView
dataGridView主要介绍绑定2种数据源,一种是list,另一种是数据库。
先看下效果吧!
首先新建一个dataGridView和一个bindingSource1控件,再按照上图建立其他的控件。首先介绍一下从数据库获取数据.
首先还是先在窗体加载事件中设置加载dataGridView一些基本参数:
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 //string strSql = "select * from sima"; 4 //GetData(strSql); 5 dataGridView1.AllowUserToAddRows = false;//禁止最后一行 6 dataGridView1.GridColor = Color.Red;//网格线 7 dataGridView1.MultiSelect = false;//禁止多行选择 8 dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;// 单击选中整行,枚举 9 //dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing; 10 dataGridView1.AllowUserToResizeColumns = false; // 禁拖动列宽度 11 dataGridView1.AllowUserToResizeRows = false; // 禁拖动行高度 12 dataGridView1.AllowUserToOrderColumns = true;//拖动 13 dataGridView1.Font = new Font("微软雅黑", 13); 14 }
为了让一个dataGridView能显示不同的表,先抽取出通过传入一个sql语句,绑定相应数据源的方法:
1 private void GetData(string strSql) 2 { 3 try 4 { 5 dataGridView1.DataSource = bindingSource1; 6 OracleConnection connection = new OracleConnection(connectionString); 7 connection.Open(); 8 //string strSql = "select * from sima"; 9 OracleDataAdapter dataAdapter = new OracleDataAdapter(strSql, connection); 10 11 DataTable table = new DataTable(); 12 table.Locale = System.Globalization.CultureInfo.InvariantCulture; 13 dataAdapter.Fill(table); 14 bindingSource1.DataSource = table; 15 // dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader); 16 } 17 catch (Exception ex) 18 { 19 MessageBox.Show(ex.Message); 20 } 21 }
自动绘制行号的事件:
1 private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) 2 { 3 if (e.ColumnIndex < 0 && e.RowIndex >= 0) // 绘制 自动序号 4 { 5 e.Paint(e.ClipBounds, DataGridViewPaintParts.All); 6 Rectangle vRect = e.CellBounds; 7 vRect.Inflate(-2, 2); 8 TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(), e.CellStyle.Font, vRect, e.CellStyle.ForeColor, TextFormatFlags.Right | TextFormatFlags.VerticalCenter); 9 e.Handled = true; 10 } 11 12 if (e.RowIndex % 2 == 0) 13 { // 行序号为双数(含0)时 14 e.CellStyle.BackColor = Color.White; 15 } 16 else 17 { 18 e.CellStyle.BackColor = Color.Honeydew; 19 } 20 e.CellStyle.SelectionBackColor = Color.Gray; // 选中单元格时,背景色 21 e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; //单位格内数据对齐方式 22 }
司马老贼:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 string strSql = "select * from sima"; 4 GetData(strSql); 5 dataGridView1.Columns[0].HeaderCell.Value = "序号"; 6 dataGridView1.Columns[1].HeaderCell.Value = "姓名"; 7 dataGridView1.Columns[2].HeaderCell.Value = "年龄"; 8 dataGridView1.Columns[3].HeaderCell.Value = "官职"; 9 dataGridView1.Columns[4].HeaderCell.Value = "朝代"; 10 dataGridView1.Columns[5].HeaderCell.Value = "攻击力"; 11 dataGridView1.Columns[6].HeaderCell.Value = "智力"; 12 }
商品:
1 private void button2_Click(object sender, EventArgs e) 2 { 3 string strSql = "select * from goods"; 4 GetData(strSql); 5 dataGridView1.Columns[0].HeaderCell.Value = "编号"; 6 dataGridView1.Columns[1].HeaderCell.Value = "商品名"; 7 dataGridView1.Columns[2].HeaderCell.Value = "数量"; 8 dataGridView1.Columns[3].HeaderCell.Value = "单价"; 9 dataGridView1.Columns[4].HeaderCell.Value = "产地"; 10 11 }
获取当前值:
1 private void button5_Click(object sender, EventArgs e) 2 { 3 textBox1.Text = dataGridView1.CurrentCell.Value.ToString(); 4 textBox2.Text = dataGridView1.CurrentCell.ColumnIndex.ToString(); 5 textBox3.Text = dataGridView1.CurrentCell.RowIndex.ToString(); 6 }
定位:
1 private void button6_Click(object sender, EventArgs e) 2 { 3 dataGridView1.CurrentCell = dataGridView1[2, 2]; 4 }
下遍历:
1 private void button7_Click(object sender, EventArgs e) 2 { 3 int row = this.dataGridView1.CurrentRow.Index + 1; 4 if (row > this.dataGridView1.RowCount - 1) 5 row = 0; 6 this.dataGridView1.CurrentCell = this.dataGridView1[0, row]; 7 }
上遍历:
1 private void button8_Click(object sender, EventArgs e) 2 { 3 int row = this.dataGridView1.CurrentRow.Index - 1; 4 if (row < 0) 5 row = this.dataGridView1.RowCount - 1; 6 this.dataGridView1.CurrentCell = this.dataGridView1[0, row]; 7 }
实现绑定list有点麻烦,但是我们只要明确一点我们要的效果是:我们的操作是对源操作,源变了,显示跟着变!或者就是对显示操作,显示变了,源跟着变!除此之外的操作方式都是极其危险的!我个人更倾向于前者!
先建一个全局的list和list中存储的实体类emplyee
1 public static List<Emplyee> emp=new List<Emplyee>();
2 public BindingList<Emplyee> empbd = new BindingList<Emplyee>(emp);
1 public class Emplyee 2 { 3 private string empName; 4 private string empAge; 5 private string empSlary; 6 7 8 public string ChangeEmpAge 9 { 10 set 11 { 12 empName = value; 13 } 14 get 15 { 16 return empName; 17 } 18 } 19 20 public string ChangeEmpName 21 { 22 set 23 { 24 empAge = value; 25 } 26 get 27 { 28 return empAge; 29 } 30 } 31 32 public string ChangeEmpSlary 33 { 34 set 35 { 36 empSlary = value; 37 } 38 get 39 { 40 return empSlary; 41 } 42 43 } 44 }
list下获取数据源的方法:
1 public void getDataFromList() 2 { 3 this.dataGridView1.DataSource = empbd; 4 }
更新数据源的方法:
1 public void updateListUi() { 2 3 this.dataGridView1.DataSource = null; 4 getDataFromList(); 5 6 }
添加记录:
private void button4_Click(object sender, EventArgs e) { dataGridView1.CellPainting += dataGridView1_CellPainting; Emplyee emplyee = new Emplyee(); emplyee.ChangeEmpName="张三"; emplyee.ChangeEmpAge = "20"; emplyee.ChangeEmpSlary = "三万"; emp.Add(emplyee); updateListUi(); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;//自动铺满 //dataGridView1.Columns[0].Width = 100; //dataGridView1.Columns[1].Width = 100; //dataGridView1.Columns[2].Width = 350; dataGridView1.Columns[0].HeaderCell.Value = "姓名"; dataGridView1.Columns[1].HeaderCell.Value = "年龄"; dataGridView1.Columns[2].HeaderCell.Value = "工资"; dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;//滚到最后 }
4 dataGridView实现分页显示
有时候数据量特别大,滚动条表示无能为力的时候,就可以考虑一下分页显示。效果如下:
首先还是先建一个dataGridView 和一个bindingSource和一个bindingnavigator(此空间有最顶部的那个效果,但是自己还要再改一下)。
首先还是窗体加载事件:
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 OracleConnection connection = new OracleConnection(connectionString); 4 DataSet ds = new DataSet(); 5 connection.Open(); 6 string strSql = "select * from sima"; 7 OracleDataAdapter command = new OracleDataAdapter(strSql, connection); 8 command.Fill(ds, "ds"); 9 connection.Close(); 10 dtInfo = ds.Tables[0]; 11 InitDataSet(); 12 }
全局变量:
1 public int pageSize = 0; //每页显示行数 2 public int nMax = 0; //总记录数 3 public int pageCount = 0; //页数=总记录数/每页显示行数 4 public int pageCurrent = 0; //当前页号 5 public int nCurrent = 0; //当前记录行 6 public DataSet ds = new DataSet(); 7 public DataTable dtInfo = new DataTable(); 8 9 public static string dataSource = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=2013-20130829TH)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=oracle)));"; 10 public static string persistSecurityInfo = "Persist Security Info=True;"; 11 public static string userID = "User ID=SYSTEM;"; 12 public static string password = "Password=admin;"; 13 public static string connectionString = dataSource + persistSecurityInfo + userID + password;
分页方法:
1 private void InitDataSet() 2 { 3 pageSize = 20; //设置页面行数 4 nMax = dtInfo.Rows.Count; 5 6 pageCount = (nMax / pageSize); //计算出总页数 7 8 if ((nMax % pageSize) > 0) pageCount++; 9 10 pageCurrent = 1; //当前页数从1开始 11 nCurrent = 0; //当前记录数从0开始 12 13 LoadData(); 14 } 15 16 private void LoadData() 17 { 18 int nStartPos = 0; //当前页面开始记录行 19 int nEndPos = 0; //当前页面结束记录行 20 21 DataTable dtTemp = dtInfo.Clone(); //克隆DataTable结构框架 22 23 if (pageCurrent == pageCount) 24 nEndPos = nMax; 25 else 26 nEndPos = pageSize * pageCurrent; 27 28 nStartPos = nCurrent; 29 30 lblPageCount.Text = pageCount.ToString(); 31 txtCurrentPage.Text = Convert.ToString(pageCurrent); 32 33 //从元数据源复制记录行 34 for (int i = nStartPos; i < nEndPos; i++) 35 { 36 dtTemp.ImportRow(dtInfo.Rows[i]); 37 nCurrent++; 38 } 39 bdsInfo.DataSource = dtTemp; 40 bdnInfo.BindingSource = bdsInfo; 41 dgvInfo.DataSource = bdsInfo; 42 }
更新数据源:
1 public void updateUI() { 2 OracleConnection connection = new OracleConnection(connectionString); 3 DataSet ds = new DataSet(); 4 connection.Open(); 5 string strSql = "select * from sima"; 6 OracleDataAdapter command = new OracleDataAdapter(strSql, connection); 7 command.Fill(ds, "ds"); 8 connection.Close(); 9 dtInfo = ds.Tables[0]; 10 InitDataSet(); 11 }
分页点击事件:
1 private void bdnInfo_ItemClicked(object sender, ToolStripItemClickedEventArgs e) 2 { 3 4 if (e.ClickedItem.Text == "关闭") 5 { 6 this.Close(); 7 } 8 if (e.ClickedItem.Text == "上一页") 9 { 10 pageCurrent--; 11 if (pageCurrent <= 0) 12 { 13 MessageBox.Show("已经是第一页,请点击“下一页”查看!"); 14 return; 15 } 16 else 17 { 18 nCurrent = pageSize * (pageCurrent - 1); 19 } 20 21 LoadData(); 22 } 23 if (e.ClickedItem.Text == "下一页") 24 { 25 pageCurrent++; 26 if (pageCurrent > pageCount) 27 { 28 MessageBox.Show("已经是最后一页,请点击“上一页”查看!"); 29 return; 30 } 31 else 32 { 33 nCurrent = pageSize * (pageCurrent - 1); 34 } 35 LoadData(); 36 } 37 }
隔行显示和行号显示事件:
1 private void dgvInfo_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) 2 { 3 if (this.dgvInfo.Rows.Count != 0) 4 { 5 for (int i = 0; i < this.dgvInfo.Rows.Count; ) 6 { 7 this.dgvInfo.Rows[i].DefaultCellStyle.BackColor = System.Drawing.Color.Pink; 8 i += 2; 9 } 10 } 11 12 13 } 14 15 private void dgvInfo_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) 16 { 17 Color color = ((DataGridView)sender).RowHeadersDefaultCellStyle.ForeColor; 18 if (((DataGridView)sender).Rows[e.RowIndex].Selected) 19 color = ((DataGridView)sender).RowHeadersDefaultCellStyle.SelectionForeColor; 20 else 21 color = ((DataGridView)sender).RowHeadersDefaultCellStyle.ForeColor; 22 23 using (SolidBrush b = new SolidBrush(color)) 24 { 25 e.Graphics.DrawString((e.RowIndex + 1).ToString(), e.InheritedRowStyle.Font, b, e.RowBounds.Location.X + 10, e.RowBounds.Location.Y + 6); 26 } 27 28 }
编辑检查事件:
1 private void dgvInfo_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) 2 { 3 DataGridView dgv = (DataGridView)sender; 4 //是否可以进行编辑的条件检查 5 if (dgv.Columns[e.ColumnIndex].Name == "Column1" && 6 !(bool)dgv["Column2", e.RowIndex].Value) 7 { 8 // 取消编辑 9 e.Cancel = true; 10 } 11 }
获取当前单元格:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 // 取得当前单元格内容 4 textBox1.Text = dgvInfo.CurrentCell.Value.ToString(); 5 // 取得当前单元格的列 Index 6 textBox2.Text = (dgvInfo.CurrentCell.ColumnIndex+1).ToString(); 7 // 取得当前单元格的行 Index 8 textBox3.Text = (dgvInfo.CurrentCell.RowIndex+1).ToString(); 9 10 }
定位:
1 private void button2_Click(object sender, EventArgs e) 2 { 3 dgvInfo.CurrentCell = dgvInfo[1, 1]; 4 }
向下遍历 向上遍历:
1 private void button3_Click(object sender, EventArgs e) 2 { 3 int row = this.dgvInfo.CurrentRow.Index + 1; 4 if (row > this.dgvInfo.RowCount - 1) 5 row = 0; 6 this.dgvInfo.CurrentCell = this.dgvInfo[0, row]; 7 } 8 9 private void button4_Click(object sender, EventArgs e) 10 { 11 int row = this.dgvInfo.CurrentRow.Index - 1; 12 if (row < 0) 13 row = this.dgvInfo.RowCount - 1; 14 this.dgvInfo.CurrentCell = this.dgvInfo[0, row]; 15 }
只读:
private void button5_Click(object sender, EventArgs e) { // dgvInfo.ReadOnly = true; // 设置 DataGridView1 的第2列整列单元格为只读 dgvInfo.Columns[1].ReadOnly = true; // 设置 DataGridView1 的第3行整行单元格为只读 dgvInfo.Rows[2].ReadOnly = true; // 设置 DataGridView1 的[0,0]单元格为只读 dgvInfo[0, 0].ReadOnly = true; }
禁止添加:
1 private void button6_Click(object sender, EventArgs e) 2 { 3 // 设置用户不能手动给 DataGridView1 添加新行 4 dgvInfo.AllowUserToAddRows = false; 5 // 禁止DataGridView1的行删除操作。 6 dgvInfo.AllowUserToDeleteRows = false; 7 }
删除提示事件:
1 private void dgvInfo_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e) 2 { 3 // 删除前的用户确认。 4 if (MessageBox.Show("确认要删除该行数据吗?", "删除确认", 5 MessageBoxButtons.OKCancel, 6 MessageBoxIcon.Question) != DialogResult.OK) 7 { 8 // 如果不是 OK,则取消。 9 e.Cancel = true; 10 } 11 }
删除指定行:
1 private void button7_Click(object sender, EventArgs e) 2 { 3 //删除名为"Column1"的列 4 dgvInfo.Columns.Remove("序号"); 5 //删除第二列 6 dgvInfo.Columns.RemoveAt(1); 7 // 删除第一行 8 dgvInfo.Rows.RemoveAt(0); 9 }
删除选定行:
1 private void button8_Click(object sender, EventArgs e) 2 { 3 foreach (DataGridViewRow r in dgvInfo.SelectedRows) 4 { 5 if (!r.IsNewRow) 6 { 7 dgvInfo.Rows.Remove(r); 8 } 9 } 10 }
自动调整:
1 private void button9_Click(object sender, EventArgs e) 2 { 3 // 设定包括Header和所有单元格的列宽自动调整 4 dgvInfo.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; 5 6 // 设定包括Header和所有单元格的行高自动调整 7 dgvInfo.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; 8 }
删除和添加:
之前有说过删除的操作一定是对源进行操作,然后再去更新页面,如果你反着操作不是不行,但是你需要实现绑定行添加和移除触发事件,反之会减少很多麻烦!
1 private void button10_Click(object sender, EventArgs e) 2 { 3 4 string sql = @"delete sima where name ='曹操'"; 5 int count = ExecuteNonQuery(connectionString, sql); 6 if(count==1){ 7 MessageBox.Show("删除成功!"); 8 } 9 updateUI(); 10 } 11 12 private void button11_Click(object sender, EventArgs e) 13 { 14 string sql = @"Insert into SIMA(SNUMBER, NAME, AGE, RATE, PLACE, FIGHT, SFROM, SIQ) Values('0', '曹操', '48', '魏王', '东汉', '95', '邺城', '85')"; 15 int count = ExecuteNonQuery(connectionString, sql); 16 if (count == 1) 17 { 18 MessageBox.Show("添加成功!"); 19 } 20 updateUI(); 21 }
5 datagridView中显示下拉列表
datagridView中显示下拉列表的实现借鉴了peterzb的代码,我只是对他的实现逻辑进行了稍微整理,想要深入研究,请看原文。
实现思路及效果如下:
首先还是新建一个dataGridview.
窗体加载事件:
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 // 绑定性别下拉列表框 4 BindSex(); 5 6 //绑定数据表 7 BindData(); 8 9 // 设置下拉列表框不可见 10 cmb_Temp.Visible = false; 11 12 // 添加下拉列表框事件 13 cmb_Temp.SelectedIndexChanged += new EventHandler(cmb_Temp_SelectedIndexChanged); 14 15 // 将下拉列表框加入到DataGridView控件中 16 this.dgv_User.Controls.Add(cmb_Temp); 17 }
新建一个下拉列表控件:
实现绑定转换的方法:
1 private void BindSex() 2 { 3 DataTable dtSex = new DataTable(); 4 dtSex.Columns.Add("Value"); 5 dtSex.Columns.Add("Name"); 6 DataRow drSex; 7 drSex = dtSex.NewRow(); 8 drSex[0] = "1"; 9 drSex[1] = "男"; 10 dtSex.Rows.Add(drSex); 11 drSex = dtSex.NewRow(); 12 drSex[0] = "0"; 13 drSex[1] = "女"; 14 dtSex.Rows.Add(drSex); 15 cmb_Temp.ValueMember = "Value"; 16 cmb_Temp.DisplayMember = "Name"; 17 cmb_Temp.DataSource = dtSex; 18 cmb_Temp.DropDownStyle = ComboBoxStyle.DropDownList; 19 }
绑定数据源:
1 private void BindData() 2 { 3 DataTable dtData = new DataTable(); 4 dtData.Columns.Add("ID"); 5 dtData.Columns.Add("Name"); 6 dtData.Columns.Add("Sex"); 7 DataRow drData; 8 drData = dtData.NewRow(); 9 drData[0] = 1; 10 drData[1] = "张三"; 11 drData[2] = "1"; 12 dtData.Rows.Add(drData); 13 drData = dtData.NewRow(); 14 drData[0] = 2; 15 drData[1] = "李四"; 16 drData[2] = "1"; 17 dtData.Rows.Add(drData); 18 drData = dtData.NewRow(); 19 drData[0] = 3; 20 drData[1] = "王五"; 21 drData[2] = "1"; 22 dtData.Rows.Add(drData); 23 drData = dtData.NewRow(); 24 drData[0] = 4; 25 drData[1] = "小芳"; 26 drData[2] = "0"; 27 dtData.Rows.Add(drData); 28 drData = dtData.NewRow(); 29 drData[0] = 5; 30 drData[1] = "小娟"; 31 drData[2] = "0"; 32 dtData.Rows.Add(drData); 33 drData = dtData.NewRow(); 34 drData[0] = 6; 35 drData[1] = "赵六"; 36 drData[2] = "1"; 37 dtData.Rows.Add(drData); 38 this.dgv_User.DataSource = dtData; 39 }
用户鼠标移到下拉列表处的事件:
1 private void dgv_User_CurrentCellChanged(object sender, EventArgs e) 2 { 3 try 4 { 5 if (this.dgv_User.CurrentCell.ColumnIndex == 2) 6 { 7 Rectangle rect = dgv_User.GetCellDisplayRectangle(dgv_User.CurrentCell.ColumnIndex, dgv_User.CurrentCell.RowIndex, false); 8 string sexValue = dgv_User.CurrentCell.Value.ToString(); 9 if (sexValue == "1") 10 { 11 cmb_Temp.Text = "男"; 12 } 13 else 14 { 15 cmb_Temp.Text = "女"; 16 } 17 cmb_Temp.Left = rect.Left; 18 cmb_Temp.Top = rect.Top; 19 cmb_Temp.Width = rect.Width; 20 cmb_Temp.Height = rect.Height; 21 cmb_Temp.Visible = true; 22 } 23 else 24 { 25 cmb_Temp.Visible = false; 26 } 27 } 28 catch 29 { 30 } 31 }
选择下拉列表框时改变DataGridView单元格的内容触发的事件:
1 private void cmb_Temp_SelectedIndexChanged(object sender, EventArgs e) 2 { 3 if (((ComboBox)sender).Text == "男") 4 { 5 dgv_User.CurrentCell.Value = "男"; 6 dgv_User.CurrentCell.Tag = "1"; 7 } 8 else 9 { 10 dgv_User.CurrentCell.Value = "女"; 11 dgv_User.CurrentCell.Tag = "0"; 12 } 13 }
滚动DataGridView触发事件:
1 // 滚动DataGridView时将下拉列表框设为不可见 2 private void dgv_User_Scroll(object sender, ScrollEventArgs e) 3 { 4 this.cmb_Temp.Visible = false; 5 } 6 7 // 改变DataGridView列宽时将下拉列表框设为不可见 8 private void dgv_User_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) 9 { 10 this.cmb_Temp.Visible = false; 11 }
绑定数据表后将性别列中的每一单元格的Value和Tag属性(Tag为值文本,Value为显示文本):
1 private void dgv_User_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) 2 { 3 for (int i = 0; i < this.dgv_User.Rows.Count; i++) 4 { 5 if (dgv_User.Rows[i].Cells[2].Value != null && dgv_User.Rows[i].Cells[2].ColumnIndex == 2) 6 { 7 dgv_User.Rows[i].Cells[2].Tag = dgv_User.Rows[i].Cells[2].Value.ToString(); 8 if (dgv_User.Rows[i].Cells[2].Value.ToString() == "1") 9 { 10 dgv_User.Rows[i].Cells[2].Value = "男"; 11 } 12 else if (dgv_User.Rows[i].Cells[2].Value.ToString() == "0") 13 { 14 dgv_User.Rows[i].Cells[2].Value = "女"; 15 } 16 } 17 } 18 }
6.0 结束
其实有关listView和dataGridView的风骚的操作还有很多,有兴趣的可以去拜读peterzb的博客,以上所有有关借鉴的内容可能不全部是引用于peterzb,但是也都是来自于其的引用,不再一一拉出来示众。