DevExpress 的GridControl实现主从报表
一、效果图
二、设置主从表
private void GetData()
{
DataTable dtTeacher = new DataTable("Tea");
dtTeacher.Columns.Add("TeacherId");
dtTeacher.Columns.Add("TeacherName");
dtTeacher.Columns.Add("Desc");
DataRow dr1 = dtTeacher.NewRow();
dr1["TeacherId"] = 1;
dr1["TeacherName"] = "孔子";
dr1["Desc"] = "子姓,孔氏,名丘,字仲尼,中国古代伟大的思想家、政治家、教育家,儒家学派创始人";
dtTeacher.Rows.Add(dr1);
DataRow dr2 = dtTeacher.NewRow();
dr2["TeacherId"] = 2;
dr2["TeacherName"] = "老子";
dr2["Desc"] = "姓李名耳,字聃,中国古代思想家、哲学家、文学家和史学家,道家学派创始人和主要代表人物";
dtTeacher.Rows.Add(dr2);
DataRow dr3 = dtTeacher.NewRow();
dr3["TeacherId"] = 3;
dr3["TeacherName"] = "庄子";
dr3["Desc"] = "名周,战国时期宋国蒙人 。战国中期思想家、哲学家、文学家,道家学派代表人物,与老子并称“老庄”。";
dtTeacher.Rows.Add(dr3);
DataRow dr4 = dtTeacher.NewRow();
dr4["TeacherId"] = 4;
dr4["TeacherName"] = "孟子";
dr4["Desc"] = "名轲,字子舆 ,邹国(今山东邹城东南)人。战国时期哲学家、思想家、教育家,是孔子之后、荀子之前的儒家学派的代表人物,与孔子并称“孔孟”。";
dtTeacher.Rows.Add(dr4);
DataRow dr5 = dtTeacher.NewRow();
dr5["TeacherId"] = 5;
dr5["TeacherName"] = "韩非子";
dr5["Desc"] = "战国末期韩国新郑(今属河南)人。中国古代思想家、哲学家和散文家,法家学派代表人物。";
dtTeacher.Rows.Add(dr5);
DataTable dtStu = new DataTable("Stu");
dtStu.Columns.Add("Id");
dtStu.Columns.Add("TeacherId");
dtStu.Columns.Add("Name");
DataRow drS1 = dtStu.NewRow();
drS1["Id"] = 1;
drS1["TeacherId"] = 1;
drS1["Name"] = "孔子1";
dtStu.Rows.Add(drS1);
DataRow drS2 = dtStu.NewRow();
drS2["Id"] = 2;
drS2["TeacherId"] = 1;
drS2["Name"] = "孔子2";
dtStu.Rows.Add(drS2);
DataRow drS3 = dtStu.NewRow();
drS3["Id"] = 3;
drS3["TeacherId"] = 1;
drS3["Name"] = "孔子3";
dtStu.Rows.Add(drS3);
DataRow drS4 = dtStu.NewRow();
drS4["Id"] = 4;
drS4["TeacherId"] = 2;
drS4["Name"] = "老子1";
dtStu.Rows.Add(drS4);
DataRow drS5 = dtStu.NewRow();
drS5["Id"] = 5;
drS5["TeacherId"] = 2;
drS5["Name"] = "老子2";
dtStu.Rows.Add(drS5);
DataSet ds = new DataSet();
ds.Tables.Add(dtTeacher);
ds.Tables.Add(dtStu);
// 设置关系,很关键
ds.Relations.Add(new DataRelation("详细信息",dtTeacher.Columns["TeacherId"],dtStu.Columns["TeacherId"]));
gridControl1.DataSource = ds.Tables[0];
// 设置第一行是否展开
gridView1.SetMasterRowExpanded(0,false);
// 设置为不能编辑
gridView1.OptionsBehavior.Editable = false;
// 折叠所有行
(gridControl1.MainView as GridView).CollapseAllDetails();
// 隐藏Tab显示的信息
gridView1.OptionsDetail.ShowDetailTabs = false;
// 展开所有的行
ExpandAllRows(gridView1,false);
// 行点击事件
gridView1.RowClick += gv_RowClick;
// 设置子母表展开时共用一个竖向滚动条
gridView1.OptionsDetail.DetailMode = DetailMode.Embedded;
// 设置子母表展开时子表达到自动高度
gridView1.DetailHeight = int.MaxValue;
}
/// <summary>
/// 行点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gv_RowClick(object sender, RowClickEventArgs e)
{
// 双击展开和折叠
if (e.Button == MouseButtons.Left && e.Clicks==2)
{
CloseExpandCur(gridView1);
}
}
/// <summary>
/// 是否展开或者折叠
/// </summary>
/// <param name="view"></param>
private void CloseExpandCur(GridView view)
{
// 获取当前点击的行
int row = view.FocusedRowHandle;
// 获取当前点击的行是否折叠
bool isExpand = view.GetMasterRowExpanded(row);
// 设置展开或者折叠
view.SetMasterRowExpanded(row,!isExpand);
}
三、是否展开的方法
由于没有提供展开所有的视图的方法,可以自己实现
/// <summary>
/// 是否展开视图
/// </summary>
/// <param name="view">视图名</param>
/// <param name="isExpand">是否展开视图</param>
private void ExpandAllRows(GridView view,bool isExpand)
{
view.BeginUpdate();
try
{
int rows = view.DataRowCount;
for (int i = 0; i < rows; i++)
{
view.SetMasterRowExpanded(i, isExpand);
}
}
finally
{
view.EndUpdate();
}
}
四、获取子View
/// <summary>
/// 获取子View
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gv_MasterRowExpanded(object sender, CustomMasterRowEventArgs e)
{
GridView viewD = gridView1.GetDetailView(e.RowHandle, e.RelationIndex) as GridView;
viewD.Columns[0].Caption = "学生ID";
viewD.Columns[1].Caption = "教师ID";
viewD.Columns[2].Caption = "姓名";
}
世界上没有什么事情是跑步解决不了的,如果有,那就再跑一会!