最近在做一个桌面项目,公司使用的是DevExpress控件,在做表单过程中,碰到了问题,DevExpress没有编辑合并单元格的功能,在Google搜到一个解决办法,姑且就拿过来用了。
但使用了之后,的确解决了自己的问题,但是同样会存在另一个问题,当我的GridView存在下拉条时,新添加的MemoEdit控件并不会随着下拉条移动。所以自己在这份代码的基础上进行修改。
废话不说直接上图。
首先建一个GridControl控件,添加几个字段
例子中我们采用可以合并的单元格是Class列和GroupIndex,GroupIndex字段作为标识字段用来区分合并单元格的,这个字段是隐藏的,其他俩字段StuName和Score是不可以合并的。
添加一个DataTable存储GridView数据
private DataTable dt;
public Form1()
{
InitializeComponent();
dt = new DataTable();
//为DataTable添加列
//班级
dt.Columns.Add("Class", typeof(string));
//学生名称
dt.Columns.Add("StuName", typeof(string));
//成绩
dt.Columns.Add("Score", typeof(string));
//用以标识合并数据集
dt.Columns.Add("GroupIndex", typeof(int));
//grid控件绑定数据
gridControl1.DataSource = dt;
}
添加DataView MouseDown事件
private void gridView1_MouseDown(object sender, MouseEventArgs e)
{
GridView view = sender as GridView;
//根据鼠标位置获取点击信息
GridHitInfo hInfo = view.CalcHitInfo(e.X, e.Y);
if (hInfo.InRowCell && hInfo.Column.FieldName == "Class")
{
//获取单元格信息
GridViewInfo vInfo = view.GetViewInfo() as GridViewInfo;
GridCellInfo cInfo = vInfo.GetGridCellInfo(hInfo);
//如果单元格为可合并的
if (cInfo is GridMergedCellInfo)
{
//MemoEdit控件属性
var edit = new MemoEdit();
edit.Bounds = cInfo.Bounds;
edit.Text = cInfo.CellValue.ToString();
//控件名称 定义为 memoedit+列名+GroupIndex值
edit.Name = "memoedit_" + hInfo.Column.FieldName + "_" + dt.Rows[hInfo.RowHandle]["GroupIndex"];
//控件鼠标离开事件
edit.MouseLeave += Edit_MouseLeave1;
//控件值改变事件
edit.EditValueChanged += Edit_EditValueChanged;
//将控件添加到GridControl中
gridControl1.Controls.Add(edit);
}
}
}
Edit_MouseLeave函数:
/// <summary>
/// 当鼠标离开合并单元格时,删除添加的MemoEdit控件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Edit_MouseLeave1(object sender, EventArgs e)
{
//遍历GridControl子控件,若名称含memoedit关键字,则获取并删除该控件
List<int> removeList = new List<int>();
for (int i = 0; i < gridControl1.Controls.Count; i++)
{
if (gridControl1.Controls[i].Name.Contains("memoedit"))
{
removeList.Add(i);
}
}
removeList.OrderByDescending(a => a);
foreach (var r in removeList)
gridControl1.Controls.RemoveAt(r);
}
Edit_EditValueChanged方法
/// <summary>
/// 当MemoEdit控件值发生改变时,修改DataTable中的值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Edit_EditValueChanged(object sender, EventArgs e)
{
MemoEdit memo = sender as MemoEdit;
var strList = memo.Name.Split('_');
if (strList[1] == "Class")
{
var group = dt.Rows.Cast<DataRow>().Where(a => a["GroupIndex"].ToString() == strList[2]).AsEnumerable();
foreach (var g in group)
{
dt.Rows[dt.Rows.IndexOf(g)]["Class"] = memo.EditValue.ToString();
}
}
}
再添加一个gridView1_CellMerge方法
/// <summary>
/// GridControl控件单元格合并控制,只有当单元格为Class,且GroupIndex值相等时的才可以合并
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void gridView1_CellMerge(object sender, CellMergeEventArgs e)
{
GridView view = sender as GridView;
string value1 = view.GetDataRow(e.RowHandle1)["GroupIndex"].ToString();
string value2 = view.GetDataRow(e.RowHandle2)["GroupIndex"].ToString();
if (e.Column.FieldName == "Class")
{
string value3 = view.GetDataRow(e.RowHandle1)["Class"].ToString();
string value4 = view.GetDataRow(e.RowHandle2)["Class"].ToString();
e.Merge = value1 == value2 && value3 == value4;
e.Handled = true;
}
}
大功告成!看看效果
编辑状态如下,鼠标在合并单元格上,会创建MemoEdit控件,让你编辑单元格,编辑过程中会触发Edit_EditValueChanged、gridView1_CellMerge事件,修改dt中的值
当鼠标移走之后,完成此次编辑,触发Edit_MouseLeave1事件,移除MemoEdit控件。