【DevExpress中文教程】如何用BandedGridView表格实现多行表头处理?

在之前的分享中介绍过实现多行表头的处理,通过手工创建字段以及映射数据源字段属性的方式实现,有些客户反映是否可以通过代码方式更方便的创建对应的处理操作,因此本篇随笔继续探讨这个多行表头的处理的操作,使用代码的方式结合扩展函数处理,快速的实现GridControl的多行表头的处理操作。

DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。

点击获取DevExpress v22.1正式版(Q技术交流:523159565)

1. 回顾使用手工创建BandedColumn和绑定字段列

在之前的文章中总结了一些GridControl控件的一些操作,其中也提到了多行表头绑定处理,如下界面所示。

有时候,我们为了一些特殊的需要,要对表头进行特别的排版,使其支持多行表头的效果,如上图所示,这样方便对各项内容进行归类显示,易于阅读,在DevExpress中应该如何实现这个效果呢?

①先在设计模式将普通的GridView转换为BandedGridView或者AdvBandedGridView,这样才能支持这种多行表头的做法,如下所示。

②定义一些字段,用来显示其中的内容,如下图所示。

③定义一些Band列,设置相关的属性,并把设计界面中的字段列表拖动到对应过的Band列上面,这样就构成了一个Band列和字段内容的对应关系。

完成上面的绑定关系后,记得设置GridView控件的属性,使其不要显示原本的ColumnHeader等内容。

设置好这些内容,才能合理、完美显示出多行表头的信息。

2. 使用代码的方式结合扩展函数处理,快速的实现GridControl的多行表头

上面的操作,适合于新手的一些简单的字段绑定处理,有时候我们为了方便,可能更倾向于使用代码的方式快速构建多行表头的操作。

我们通过查看代码,可以了解GridBand对象是一个嵌套的关系,它类似树形结构,可以有很多层的子集合,也就是嵌套的头部条,它结合字段列对象GridColumn就形成了BandedGridColumn的信息。

我们需要知道GridBand只是一个头部的条状列信息,一般用来覆盖GridColumn的默认列头信息,因此需要设置一定的样式来禁用显示默认的GridColumn的头部信息。

view.OptionsView.ShowColumnHeaders = false; //因为有Band列了,所以把ColumnHeader隐藏

因此我们创建一个扩展的静态类文件,并加入设置BandedGridView样式的处理扩展方法,把相关的样式统一处理,如下所示。

/// <summary>
/// GridView及其RepositoryItem编辑控件的扩展类
/// </summary>
public static class Grid_Extension
{
/// <summary>
/// 设置BandedGridView的样式
/// </summary>
/// <param name="view"></param>
public static void SetBandedViewStyle(this BandedGridView view)
{
view.BeginUpdate(); //开始视图的编辑,防止触发其他事件
view.Bands.Clear();
//修改附加选项
view.OptionsView.ShowColumnHeaders = false; //因为有Band列了,所以把ColumnHeader隐藏
view.OptionsView.ShowGroupPanel = false; //如果没必要分组,就把它去掉
view.OptionsView.EnableAppearanceEvenRow = false; //是否启用偶数行外观
view.OptionsView.EnableAppearanceOddRow = true; //是否启用奇数行外观
view.OptionsView.ShowFilterPanelMode = ShowFilterPanelMode.Never; //是否显示过滤面板
view.OptionsCustomization.AllowColumnMoving = false; //是否允许移动列
view.OptionsCustomization.AllowColumnResizing = false; //是否允许调整列宽
view.OptionsCustomization.AllowGroup = false; //是否允许分组
view.OptionsCustomization.AllowFilter = false; //是否允许过滤
view.OptionsCustomization.AllowSort = true; //是否允许排序
view.OptionsSelection.EnableAppearanceFocusedCell = true; //是否焦点显示选中的单元格
view.EndUpdate(); //结束视图的编辑
}

由于GridBand可能是嵌套的多层表头,因此为了方便,可以单独设置一个扩展方法创建GridBand,这样有助于引用对象。

/// <summary>
/// 创建绑定Banded列
/// </summary>
/// <param name="view"></param>
/// <param name="caption"></param>
/// <param name="width"></param>
/// <param name="fixedStyle"></param>
/// <param name="visible">是否可见</param>
/// <returns></returns>
public static GridBand CreateBand(this BandedGridView view, string caption, int width = 80, FixedStyle fixedStyle = FixedStyle.None, bool visible = true)
{
//使用多语言处理标题
caption = JsonLanguage.Default.GetString(caption);
var band = new GridBand
{
Caption = caption,
Width = width,
Fixed = fixedStyle,
Visible = visible,
};
view.Bands.Add(band);
band.VisibleIndex = view.Bands.Count;
band.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center;
return band;
}

这样我们就可以传递GridBand对象来构建多层级的字段列信息了,利用扩展函数,我们可以方便的实现创建绑定列信息。

/// <summary>
/// 根据指定的GridBand父级对象,构建BandedGridColumn列对象
/// </summary>
/// <param name="view"></param>
/// <param name="band"></param>
/// <param name="fieldName"></param>
/// <param name="caption"></param>
/// <param name="allowEdit"></param>
/// <param name="allowMerge"></param>
/// <returns></returns>
public static BandedGridColumn CreateBandColumn(this BandedGridView view, GridBand band, string fieldName, string caption, bool allowEdit = true, DefaultBoolean allowMerge = DefaultBoolean.False)
{
//使用多语言处理标题
caption = JsonLanguage.Default.GetString(caption);
var gridColumn = new BandedGridColumn()
{
FieldName = fieldName,
Caption = caption,
UnboundType = UnboundColumnType.Bound,
Visible = true
};
band.AppearanceHeader.BackColor = Color.LightGreen;

var newBand = band.Children.AddBand(caption);
newBand.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center; //文本居中
newBand.Columns.Add(gridColumn);

gridColumn.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center;
gridColumn.AppearanceCell.TextOptions.VAlignment = VertAlignment.Center;

gridColumn.OptionsColumn.AllowEdit = allowEdit;
if (!allowEdit)
{
gridColumn.AppearanceHeader.ForeColor = Color.Gray;
}

bool allowCellMerge = !view.OptionsView.AllowCellMerge && allowMerge == DefaultBoolean.True;
if (allowCellMerge)
{
view.OptionsView.AllowCellMerge = true;
}
gridColumn.OptionsColumn.AllowMerge = allowMerge;
return gridColumn;
}

而如果一般的列,没有多层嵌套的GridBand,也就是只有一层的表头,我们也需要根据字段信息进行构建一个GridBandColumn来显示信息,如下所示。

/// <summary>
/// 根据字段信息,构建BandedGridColumn列对象
/// </summary>
/// <param name="view">视图对象</param>
/// <param name="fieldName">字段名称</param>
/// <param name="caption">显示名称</param>
/// <param name="width">列宽度</param>
/// <param name="fixedStyle">固定显示模式</param>
/// <param name="visible">是否可见</param>
/// <param name="allowEdit">是否可编辑</param>
/// <param name="allowMerge">是否可合并</param>
/// <param name="unboundColumnType">绑定类型,默认为UnboundColumnType.Bound</param>
/// <returns></returns>
public static BandedGridColumn CreateBandColumn(this BandedGridView view, string fieldName, string caption, int width = 80, FixedStyle fixedStyle = FixedStyle.None, bool visible = true, bool allowEdit = true, DefaultBoolean allowMerge = DefaultBoolean.False, UnboundColumnType unboundColumnType = UnboundColumnType.Bound)
{
//使用多语言处理标题
caption = JsonLanguage.Default.GetString(caption);
var gridColumn = new BandedGridColumn()
{
FieldName = fieldName,
Caption = caption,
Width = width,
UnboundType = unboundColumnType,
};
var band = view.CreateBand(caption, width, fixedStyle);
band.Visible = visible;
band.Columns.Add(gridColumn);
//view.Columns[fieldName].OwnerBand = band;
gridColumn.AbsoluteIndex = view.Columns.Count;
gridColumn.Visible = visible;//是否可见
if (visible)
{
gridColumn.VisibleIndex = view.Columns.Count;
}
gridColumn.AppearanceHeader.TextOptions.HAlignment = HorzAlignment.Center;
gridColumn.AppearanceCell.TextOptions.VAlignment = VertAlignment.Center;

gridColumn.OptionsColumn.AllowEdit = allowEdit;
if (!allowEdit)
{
gridColumn.AppearanceHeader.ForeColor = Color.Gray;
}
bool allowCellMerge = !view.OptionsView.AllowCellMerge && allowMerge == DefaultBoolean.True;
if (allowCellMerge)
{
view.OptionsView.AllowCellMerge = true;
}
gridColumn.OptionsColumn.AllowMerge = allowMerge;
gridColumn.Fixed = fixedStyle;

return gridColumn;
}

有了这些扩展函数的铺垫,我们在实际界面中展示多层级的多行表头就会变得很容易了。为了方便介绍,我创建一个简单的窗体用来展示多行表头的代码绑定处理。

创建一个默认的窗体,放置GridControl,并把默认的GridView视图,转换为BandedGridView视图对象,如下所示。

为了绑定一些字段信息供显示、编辑处理,我们创建了一个表格,包含信息:Id,姓名,外科皮肤科_诊断,外科皮肤科_结论,神经精神科_诊断,神经精神科_结论,内科_诊断,内科_结论,眼科_诊断,眼科_结论,检查时间,备注 等字段内容,如下代码所示。

var table = DataTableHelper.CreateTable("Id|int,姓名,外科皮肤科_诊断,外科皮肤科_结论,神经精神科_诊断,神经精神科_结论,内科_诊断,内科_结论,眼科_诊断,眼科_结论,检查时间,备注");

//准备飞行员体检测试数据
for (int i =1; i <= 50;i++)
{
var dr = table.NewRow();
dr["Id"] = i;
dr["姓名"] = $"某某{i}";

dr["外科皮肤科_诊断"] = "健康";
dr["外科皮肤科_结论"] = "合格";

dr["神经精神科_诊断"] = "健康";
dr["神经精神科_结论"] = "合格";

dr["内科_诊断"] = "健康";
dr["内科_结论"] = "合格";

dr["眼科_诊断"] = "健康";
dr["眼科_结论"] = "合格";

dr["检查时间"] = DateTime.Now;
dr["备注"] = "";

table.Rows.Add(dr);
}

首先需要创建GridView的初始化信息,如绑定那些字段列,结合多表头的处理方式,如下代码所示。

/// <summary>
/// 初始化列表
/// </summary>
private void InitGridView()
{
var grid = this.gridControl1;
var grv = this.gridControl1.MainView as BandedGridView;
grid.ContextMenuStrip = this.contextMenuStrip1;//右键菜单
//初始化GridView样式,并设置相关的BandedGridView样式
grv.InitGridView(GridType.EditOnly, false, EditorShowMode.MouseDownFocused, "");
grv.SetBandedViewStyle();

//创建显示的列:
//Id,姓名,外科皮肤科_诊断,外科皮肤科_结论,神经精神科_诊断,神经精神科_结论,内科_诊断,内科_结论,眼科_诊断,眼科_结论,检查时间,备注
grv.Columns.Clear();
grv.CreateBandColumn("Id", "Id", 80, FixedStyle.Left, true, false);
grv.CreateBandColumn("姓名", "客户名称", 80, FixedStyle.Left, true, false);

var band1 = grv.CreateBand("外科皮肤科", 120);
grv.CreateBandColumn(band1, "外科皮肤科_诊断", "诊断");
grv.CreateBandColumn(band1, "外科皮肤科_结论", "结论");

var band2 = grv.CreateBand("神经精神科", 120);
grv.CreateBandColumn(band2, "神经精神科_诊断", "诊断");
grv.CreateBandColumn(band2, "神经精神科_结论", "结论");

var band3 = grv.CreateBand("内科", 120);
grv.CreateBandColumn(band3, "内科_诊断", "诊断");
grv.CreateBandColumn(band3, "内科_结论", "结论");

var band4 = grv.CreateBand("眼科", 120);
grv.CreateBandColumn(band4, "眼科_诊断", "诊断");
grv.CreateBandColumn(band4, "眼科_结论", "结论");

var colCheckTime = grv.CreateBandColumn("检查时间", "检查时间").CreateDateEdit();//可修改
colCheckTime.EditMask = "yyyy-MM-dd";
colCheckTime.DisplayFormat.FormatString = "yyyy-MM-dd";
colCheckTime.EditFormat.FormatString = "yyyy-MM-dd";
colCheckTime.CustomDisplayText += (s, e) =>
{
if (e.Value != null && e.Value.ToString() != "")
{
if (Convert.ToDateTime(e.Value) <= Convert.ToDateTime("1900-1-1"))
{
e.DisplayText = "";
}
else
{
e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd");
}
}
};
//可修改
grv.CreateBandColumn("备注", "备注", 200);

//设置部分字段不可修改
var editFields = "外科皮肤科_诊断,外科皮肤科_结论,神经精神科_诊断,神经精神科_结论,内科_诊断,内科_结论,眼科_诊断,眼科_结论,检查时间,备注";
grv.SetColumnsReadOnly("*", false);
grv.SetColumnsReadOnly(editFields, true);

//检查输入
grv.ValidateRow += (s, e) =>
{
//校验一些不能为空的字段
//var result = grid.ValidateRowNull(e, new string[]
//{
// "产品编码",
// "产品名称"
//});
};
//值更改触发
grv.CellValueChanged += (s, e) =>
{
//根据数量计算金额
//if (e.Column.FieldName == "Quantity" && e.Value != null)
//{
// var Price = string.Concat(grv.GetFocusedRowCellValue("Price")).ToDecimal();
// var Quantity = string.Concat(e.Value).ToDecimal();
// grv.SetFocusedRowCellValue("Amount", Price * Quantity);
//}
};
//单元格样式
grv.RowCellStyle += (s, e) =>
{
//设置特殊颜色标志
if (editFields.Contains(e.Column.FieldName))
{
e.Appearance.BackColor = Color.Azure;
e.Appearance.ForeColor = Color.Blue;
}
};
}

初始化BandedGridView信息后,如需绑定数据,那么还需要对GridControl的数据源进行绑定才能进行编辑或者显示,如下所示的代码操作。

/// <summary>
/// 绑定数据列表
/// </summary>
private void BindData()
{
var table = DataTableHelper.CreateTable("Id|int,姓名,外科皮肤科_诊断,外科皮肤科_结论,神经精神科_诊断,神经精神科_结论,内科_诊断,内科_结论,眼科_诊断,眼科_结论,检查时间,备注");

//准备飞行员体检测试数据
for (int i =1; i <= 50;i++)
{
var dr = table.NewRow();
dr["Id"] = i;
dr["姓名"] = $"某某{i}";

dr["外科皮肤科_诊断"] = "健康";
dr["外科皮肤科_结论"] = "合格";

dr["神经精神科_诊断"] = "健康";
dr["神经精神科_结论"] = "合格";

dr["内科_诊断"] = "健康";
dr["内科_结论"] = "合格";

dr["眼科_诊断"] = "健康";
dr["眼科_结论"] = "合格";

dr["检查时间"] = DateTime.Now;
dr["备注"] = "";

table.Rows.Add(dr);
}

//绑定数据源
var grv = this.bandedGridView1;
grv.GridControl.DataSource = table;
grv.RefreshData();
}

最后,我们把它放在开发框架(如有Winform界面部分的SqlSugar开发框架、Winform开发框架)的综合演示案例里面,供参考使用。界面效果如下所示。

对比手工的效果:

实现功能差不多,通过代码方式,相对更加灵活一些。

以上就是综合介绍了手工处理和代码处理两种方式构建多行表头的处理操作,通过使用扩展函数方式,可以更快捷、更灵活的创建多表头的处理和数据的绑定展示,可以有效的减少我们在多表头上的操作摸索时间。

本文转载自:博客园 - 伍华聪

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DevExpress是一家领先的软件开发公司,提供了丰富的控件库和开发工具,可用于各种平台(如WinForms,ASP.NET等)。随着越来越多的开发者关注DevExpress,他们也提供了一些很好的中文教程来帮助我们更好地使用其工具。 首先,DevExpress的官方网站提供了很多帮助文档,其中也包括一些中文教程。在官方网站上,您可以访问DevExpress的学习中心,在此处,所有文档都有相应的PDF文件,以方便用户下载。 此外,除了官方文档,我们还可以在其社区博客和论坛上找到一些很好的中文教程DevExpress社区博客是一个非常好的资源,您可以在这里获得其他开发人员的建议和提示,这也是自学的一个很好的地方。 最后,还有一些博客文章和视频教程,这些都是由开发社区撰写的,对了解DevExpress控件和工具的使用非常有帮助。您可以使用搜索引擎查找“DevExpress中文教程”或在社交媒体上寻找相关信息,例如微博或知乎。 总之,DevExpress提供了很多非常好的教程和资源,可以帮助我们更好地了解框架和控件的应用。中文社区也很活跃,您可以在此找到很多导师或者同行的支持和帮助,使您更好地掌握DevExpress的开发过程。 ### 回答2: DevExpress是一家专业的软件开发工具提供商,其产品广泛应用于各类开发领域。对于初学者而言,了解DevExpress的各个组件和使用方法并不是易事。因此,对于需要学习DevExpress中文开发者,可以通过以下途径获取相关教程: 首先,可以从DevExpress官网上获取相关的中文教程。官网上提供了丰富的教程资源,包括中文文档、示例代码、帮助文档等。可以通过阅读官网上的教程,快速地掌握各个组件的使用方法和实现技巧。 其次,可以参考一些DevExpress中文学习笔记和博客。在网络上有很多DevExpress的学习笔记和博客,其中不乏一些中文内容的文章。这些文章通过实际案例的分析和讲解,可以帮助开发者更好地理解DevExpress组件的使用方法和实现技巧。 此外,还可以参加一些DevExpress的课程培训和在线教学。DevExpress官方网站上有丰富的教学资源,不仅提供了在线课程、视频教程和直播课程等多种学习方式,而且还有强大的在线论坛以及社区支持,可以快速解决使用中的问题和疑惑。 综上所述,无论是通过官网教程、学习笔记还是课程培训等多种途径,都可以快速地学习掌握DevExpress的组件使用方法,并且在实际开发中更加得心应手。 ### 回答3: DevExpress是一家专门提供软件开发工具和组件的公司,其产品包括WinForms、ASP.NET、Silverlight等多种类型的开发工具。因为其产品功能强大、易于使用、性能优越等优点,越来越多的软件开发人员开始使用DevExpress进行开发。 作为DevExpress用户,获取中文教程的方法有多种。其中,官方网站提供了大量的中文技术文档和教程,这些文档和教程可以根据开发者的需要和水平进行选择,从入门到进阶都有相应的内容。此外,DevExpress还提供了在线视频教程,让开发者能够更加直观地了解和学习其产品的使用。 同时,开发者还可以通过各种社区和论坛获取相关的中文教程和问题解答。在互联网上,有许多针对DevExpress的论坛和社区,其中许多高水平的开发者会主动分享自己的经验和技巧,让新手能够快速进入开发者圈子,提高自己的开发能力。 总之,对于想要学习和使用DevExpress的开发者来说,获取中文教程的方法不止一种。通过适当的学习和实践,开发者可以快速了解和掌握该产品的使用,从而在软件开发过程中拥有更多的灵活性和创造力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值