http://www.cnblogs.com/lichence/archive/2011/08/18/2145001.html
DataGridView是WinForm中非常灵活的一个控件,对于扩展其折叠功能的控件在网上已经有很多文章,但是只简要介绍了实现的方法,没有继续封装其他方法,比如数据绑定和增删功能,都需要在后置代码自己编写,加之复杂的业务逻辑,让代码显得冗余且不易复用。
在前人的基础上,利用封装好的CollapseDataGridViewRow和CollapseDataGridViewRowCollection类,对CollapseDataGridView进行了功能扩展,新增了几个泛型方法和委托事件,尽量降低了控件逻辑与业务逻辑的耦合。
新增了CollapseDataGridViewEventArgs事件参数,包含bool Result/执行结果,int RowIndex/影响的行号,string ErrorMessage/错误信息
在CollapseDataGridViewRow类中增加了GroupTag属性,用于保存集合信息,Tag用于保存集合首行对应的条目实例
在使用该控件前,需要定义三个类型,以代表团和运动员为例:
- Athlete 条目类
- AthleteItemList : List<Athlete> 集合类,可以添加一些集合自有属性,用于保存条目的公共信息
- AthleteGroupList : List<List<Athlete>> 集合列表类,调用控件BindDataSource<GL, T>(GL groupList) where GL : List<List<T>>方法时使用
初始列表需要用户自己组织好AthleteGroupList列表,对控件进行数据绑定。将控件从左侧工具箱拖拽入设计区
像使用一般的DataGridView一样,对控件进行DataPropertyName的设置,否则在使用默认数据绑定方法时无法绑定该数据行(自定义绑定方法除外)。此外SortMode属性设置为NotSortable,排序有点小复杂,还没动手做。。。
在CollapseDataGridView增加了如下几个属性,用于控制外观:
完成以上设置就可以开始编写后台代码了。可以根据需要预先绑定几个事件,用于在列表数据发生变化时,处理业务逻辑。
提供的事件如下:
- OnBindDataDetail:数据绑定事件,在调用BindDataSource<GL, T>(GL groupList) 方法后,触发该事件,返回(object item/条目实例, int rowIndex/条目所在行号, bool isMainItem/条目是否为集合首行),可以根据三者条件编写绑定行Cell显示数据的逻辑。
- AddGroupCompleted:新增集合事件,返回(object group/集合实例, CollapseDataGridViewEventArgs e/事件参数)
- RemoveGroupCompleted:移除集合事件
- AddItemCompleted:新增条目事件
- RemoveItemCompleted:移除条目事件
- OnDataCountChanged:集合或条目数量改变事件,可用于更新UI
//注册行绑定事件 -- 可以去掉该行注释,使用自定义绑定行数据模式
//this.cdgvAthleteInfo.OnBindDataDetail += new CollapseDataGridView.BindDataDetailHandler(cdgvAthleteInfo_OnBindDataDetail);
//注册新增集合事件
this.cdgvAthleteInfo.AddGroupCompleted += new CollapseDataGridView.AddGroupHandler(cdgvAthleteInfo_AddGroupCompleted);
//注册删除集合事件
this.cdgvAthleteInfo.RemoveGroupCompleted += new CollapseDataGridView.RemoveGroupHandler(cdgvAthleteInfo_RemoveGroupCompleted);
//注册新增条目事件
this.cdgvAthleteInfo.AddItemCompleted += new CollapseDataGridView.AddItemHandler(cdgvAthleteInfo_AddItemCompleted);
//注册删除条目事件
this.cdgvAthleteInfo.RemoveItemCompleted += new CollapseDataGridView.RemoveItemHandler(cdgvAthleteInfo_RemoveItemCompleted);
//注册数据源数量变更事件
this.cdgvAthleteInfo.OnDataCountChanged += new CollapseDataGridView.DataCountChangedHandler(cdgvAthleteInfo_OnDataCountChanged);
提供的公共接口如下:
- 数据源绑定方法:void BindDataSource<GL, T>(GL groupList) where GL : List<List<T>>,GL为集合列表的类型,T为条目类型,如果用户没有注册OnBindDataDetail事件,则使用默认的数据绑定方式,CollapseDataGridView中每个集合的[0,0]位置显示分组标记的值,[i,0](i > 0)的位置不显示分组标记的值。该方法通过控件每列设置的DataPropertyName从提供的GL数据源中反射出相应的值,并绑定在Cell的Value中,没有反射到属性则绑定null。
- 获取集合信息方法:G GetGroupInfo<G>(),G为集合类型,返回选中行所在集合的信息
- 新增条目方法:void AddItem<G, T>(T item) where G : List<T>,G为集合类型,T为条目类型。之所以需要传入集合类型,是因为当传入null集合时或当前CollapseDataGridView为空,目标行将作为新的集合加入CollapseDataGridView中,则需要使用G反射获得其实例,绑定在GroupTag中,随后使用G GetGroupInfo<G>()方法时,才能由object转换成G类型,若以List<T>绑定在GroupTag中,取回时,G类型中的公共属性会丢失。
- 插入条目方法:void InsertItem<G, T>(T item) where G : List<T>
- 移除条目方法:void RemoveItem<T>(int itemIndex)
- 新增集合方法:void AddGroup<G, T>(G group) where G : List<T>
- 插入集合方法:void InsertGroup<G, T>(G group) where G : List<T>
- 移除集合方法:void RemoveGroup(int itemIndex)
以上方法都对应了上面提到的事件,可以获取相应的参数,进行一些业务逻辑的处理。
不足和可能存在的Bug:
- 异常处理尚未完善,可能存在未知的异常
- 泛型的使用和部分代码冗余
个人学习,欢迎指正,仅供参考