最近项目用到此功能,找了一些资料 ,并自己做了个测试。上代码:
定义一个类:
class Student
{
public string Name { get; set; }
public string ClassName { get; set; }
public int Age { get; set; }
public string StuNo { get; set; }
}
定义全局变量:
Hashtable ht;//存储父节点状态
程序初始化或者加载后向类中添加数据:
List<Student> list = new List<Student>()
{
new Student{Name="aaa",ClassName="a",Age=20,StuNo="a001"},
new Student{Name="bbb",ClassName="a",Age=18,StuNo="a003"},
new Student{Name="ccc",ClassName="b",Age=20,StuNo="b001"},
new Student{Name="ddd",ClassName="b",Age=20,StuNo="b045"},
new Student{Name="eee",ClassName="c",Age=20,StuNo="c001"},
new Student{Name="fff",ClassName="c",Age=20,StuNo="c008"},
new Student{Name="ggg",ClassName="c",Age=20,StuNo="c050"},
new Student{Name="hhh",ClassName="c",Age=20,StuNo="c007"},
new Student{Name="hjj",ClassName="d",Age=22,StuNo="d007"}
};
初始化的时候动态添加列名:
DataGridViewTextBoxColumn txtKey = new DataGridViewTextBoxColumn();
txtKey.Name = "txtKey";
txtKey.HeaderText = "班级";
this.dataGridView1.Columns.Add(txtKey);
DataGridViewTextBoxColumn txtValue = new DataGridViewTextBoxColumn();
txtValue.Name = "txtValue";
txtValue.HeaderText = "姓名";
this.dataGridView1.Columns.Add(txtValue);
DataGridViewTextBoxColumn txtStatus = new DataGridViewTextBoxColumn();
txtStatus.Name = "txtStatus";
txtStatus.HeaderText = "年龄";
this.dataGridView1.Columns.Add(txtStatus);
DataGridViewTextBoxColumn txtStudentID = new DataGridViewTextBoxColumn();
txtStudentID.Name = "txtStudentID";
txtStudentID.HeaderText = "学号";
this.dataGridView1.Columns.Add(txtStudentID);
DataGridViewTextBoxColumn txtStuKey = new DataGridViewTextBoxColumn();
txtStuKey.Name = "txtStuKey";
txtStuKey.Visible = false;
txtStuKey.HeaderText = "班级";
this.dataGridView1.Columns.Add(txtStuKey);
将List转换为Dictionary:
Dictionary<string, List<Student>> stuGroup = new Dictionary<string, List<Student>>();
foreach (Student item in list)
{
if (!stuGroup.Keys.Contains(item.ClassName))
{
stuGroup.Add(item.ClassName, new List<Student>());
}
stuGroup[item.ClassName].Add(item);
}
循环向dataGridView中添加数据:
String sKey = String.Empty;
String sClsName = String.Empty;
String sValue = String.Empty;
String sStatus = String.Empty;
String sStuId = String.Empty;
int nRow = 0;
int nChild = 1;
foreach (KeyValuePair<string, List<Student>> item in stuGroup)
{
if (item.Key != null)
{
if (nRow>1)
{
nRow += 1;
}
DataGridViewRow dbRow = new DataGridViewRow();
this.dataGridView1.Rows.Add(dbRow);
this.ht = new Hashtable();
sKey = item.Key;
this.ht.Add(item.Key, false);
this.dataGridView1.Rows[nRow].Cells[0].Value = item.Key;//父级显示
this.dataGridView1.Rows[nRow].Cells[4].Value = item.Key;//父级,注意这里 避免dataGridView1_RowPostPaint事件中强转出错
foreach (Student stu in item.Value)
{
if (item.Value != null || item.Value.Count != 0)
{
DataGridViewRow childRow = new DataGridViewRow();
this.dataGridView1.Rows.Add(childRow);
sValue = stu.Name;
sStatus = stu.Age.ToString();
sStuId = stu.StuNo;
sClsName = stu.ClassName;
this.dataGridView1.Rows[nRow+1].Cells[1].Value = sValue;//姓名
this.dataGridView1.Rows[nRow+1].Cells[2].Value = sStatus;//年龄
this.dataGridView1.Rows[nRow+1].Cells[3].Value = sStuId;//学号
this.dataGridView1.Rows[nRow+1].Cells[4].Value = sClsName;//父级,注意这里 避免dataGridView1_RowPostPaint事件中强转出错
}
//注意这个变量必须放在子循环中
nRow++;
}
}
}
添加dataGridView的RowHeaderMouseClick事件:
private void dataGridView1_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
//通过Hashtable比对数据
String sParent = dataGridView1.Rows[e.RowIndex].Cells[4].Value.ToString();
String sName = "";
if (null == this.dataGridView1.Rows[e.RowIndex].Cells[0].Value)
{
sName = "0";
}
else
{
sName = dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString();
}
if (sParent != null)
{
ht[sName] = !Convert.ToBoolean(ht[sName]);
//重绘之前要显示所有行,否则隐藏行不会再绘制
foreach (DataGridViewRow gr in dataGridView1.Rows)
{
if (false == gr.Visible)
{
gr.Visible = true;
}
}
dataGridView1.Refresh();
dataGridView1.EndEdit();
}
}
添加dataGridView的RowPostPaint事件:
private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
if (this.dataGridView1.Rows[e.RowIndex].Cells[0].Value != null)//当前行为父节点时绘制图标
{
Rectangle rectangle = new Rectangle(e.RowBounds.Location.X + this.dataGridView1.RowHeadersWidth - 20
, e.RowBounds.Location.Y + 4, 14, 14);
Image img = Convert.ToBoolean(ht[this.dataGridView1.Rows[e.RowIndex].Cells[0].Value])
? Properties.Resources.minus : Properties.Resources.plus;
e.Graphics.DrawImage(img, rectangle);
}
else
{
this.dataGridView1.Rows[e.RowIndex].Visible = Convert.ToBoolean(ht[this.dataGridView1.Rows[e.RowIndex].Cells[4].Value]);
//this.dataGridView1.Rows[e.RowIndex].Visible = false;
}
}
没有过多的注释。将代码复制执行就可以了。