这周因为某个需求,开始学习使用 TcxGridDbLayoutView,结果本周是极其痛苦的一周。
总体而言,CxGrid是一把双刃剑,它提供了强大的功能,颠覆了VCL中Grid的传统设计思路,但也引入了巨大的复杂性,使得学习难度大幅度增加,上手很慢。而这次尝试使用的TcxGridDbLayoutView更是如此。
而且,因为CxGrid的不断发展,很多属性和方法被废弃,考虑到老版本的兼容性,这些属性和方法仍然保留类下来,因此相似的属性和方法散落在各处,给学习者造成很大的干扰。
TcxGridDbLayoutView实质是把TcxGridLayoutView和TdxLayoutControl整合在一起的一个玩意儿。
LayoutView 提供了把数据集中的Cell用容器包裹起来,想窗体一样重新排布在View中的能力。
LayoutControl提供了用户自定义界面布局的能力,包括移除、拖入、重拍窗体中容器的功能,每个容器中可以放入任何Tcontrol的后裔。
这次采用 TcxGridDbLayoutView 的原因就是需要显示 单条记录的Form形式布局(支持用户自定义)+2个DBGridEh(嵌入容器)。
学习TcxGrid,最大的困难在于 cxGrid庞大的体系结构难以理清。这里简单的记录一下一些难以摸索的地方。
TcxGridDBLayoutView
【方法】
CreateItem:TcxGridDBLayoutViewItem。此方法创建的Item,是可以绑定到数据集中某个字段的Item,也是在Customization中可以看到的items.
function GetItemByFieldName(const AFieldName: string): TcxGridDBLayoutViewItem;
通过字段名返回Item
【属性】
property Items[Index: Integer]: TcxGridDBLayoutViewItem;
property Container: TcxGridLayoutContainer;
这里的TcxGridLayoutContainer就是LayoutControl的后裔类。就是具有form布局能力的一个类。
TcxGridLayoutContainer = class(TdxLayoutContainer)
TcxGridLayoutContainer.Root: 根Group
注意:这部分知识就涉及到ExpressLayout Control。
还有一个重要的属性,就是TcxGridLayoutViewItem.LayoutItem
property LayoutItem: TcxGridLayoutItem;
简单的说,TcxGridLayoutViewItem是绑定数据的Item,用于显示数据。
而TcxGridLayoutViewItem.LayoutItem:TcxGridLayoutItem 是用于界面布局的 item 。
至此,TcxGridLayoutContainer 和 TcxGridLayoutViewItem.LayoutItem 相配合,就可以完成 界面布局的目的。
同时,如果在TcxGridLayoutContainer中CreateItem得到TdxLayoutItem ,然后给TdxLayoutItem.Control属性赋值为一个控件,就可以完成嵌入动作。
值得一提的是,TcxGridLayoutViewItem本身看起来像一个Edit,但要向Edit一样设置它的属性,是搞不定的,只能通过它只有的属性设置一下LookAndFeel等外观。要真正像Edit一样设置它的属性,比如数据的水平对齐方向,可以给TcxGridLayoutViewItem.PropertiesClass赋值,使其真正成为一个Edit,然后就可以像设置EDIT一样设置它。这一点我摸索了很久。
至于在LayOutControl中的用法,主要就是可以创建Group和Item,Group是个容器,可以装入Group和Item。
Group可以设置Border和Caption,还有ExpandButton(运行期展开和收缩Group),还可以在ExpandButton周围添加自己的Button,定义Button的Handle。
Group支持水平和垂直两种布局。别忘了,layoutControl.Root也是一个Group,通过水平和垂直排列方向+Group的嵌套,从而完成Form的布局。
而Item.Control,之前已经说了,可以放入任何Tcontrol的后裔控件。
本周结束后,我已经放弃使用 TcxGridDbLayoutView,因为嵌入的外部Grid,存在线程同步的问题。
当在cxGrid中添加了多个Level+View时,cxGrid显示为Tab方式。在切换tab时,嵌入外部Grid的TcxGridDbLayoutView会报出“System Error 1400 Invalid Window Handle”,这个问题是从cxGrid内部报出来的,简单的搜索了一下,说是线程未同步造成的。
而另一个比较严重的问题是,在设计期,点击TcxGridDbLayoutView的Edit Data and Layout,可以进行界面设计,对TcxGridDbLayoutViewItem.LayoutItem进行布局。
但一旦运行起来之后,所初始化的界面却不是当初设计的界面,特别是当你需要动态的CreateGroup/CreateItem之后。
这样一来,设计期的工作就变得没有意义。而当你企图动态创建对象进行布局时,你却无法使用Container.Clear方法,这会导致TcxGridDBLayoutViewItem也被删除掉,所以感觉这控件还不是太成熟。