一 优化理由
如下图所示,如果按照C1FlexGrid自带的单元格边框设置,即对每个单元格的CellStyle的BorderThickness进行设置,会得到如下图的效果:
其中,明显可以看到如果两个相邻的单元格同时设置了那条相邻的边,则会看起来很粗……原因很简单,C1FlexGrid是在Grid的基础上扩展,并且对每个单元格的绘制都是通过嵌套一层Border处理的,然后楼主就闲着dt自己用Grid模拟了一个简单的C1FlexGrid表格,然后用Border嵌套放入,设置了一下Border的边框,效果一模一样啊,重叠部分都变粗了;还有一个问题就是,C1FlexGrid可以设置GridLinesBrush属性,来显示默认的条条框框的显示(即时未设置单元格边框),如图中的灰色线条。但是问题来了,如图中(1,0,0,0)单元格设置,右侧和下方的默认线条没了,偶虽然不想要该单元格右边框和下边框,但你也不能把默认的条条框框的线条给弄没了啊……
这对于处女座的楼主来说,简直是不可容忍的缺陷啊,于是楼主就参照C1FlexGrid的Demo工程ExcelBook 5.0做了自己的优化处理,并将该优化应用到一直在持续完善的仿Excel扩展C1FlexGrid控件中去。
二 优化思路
在Demo——ExcelBook 5.0中有如下一段代码,可以看出来,它们在每个单元格的内容外围嵌套了四层Border,分别来绘制单元格的上、下、左、右边框及其颜色:
1 // ** overrides 2 public override void Apply(Border bdr, SelectedState selState) 3 { 4 base.Apply(bdr, SelectedState.None) 5 ApplyBorder(bdr, _bdrLeft, new Thickness(_bdrThickness.Left, 0, 0, 0)) 6 ApplyBorder(bdr, _bdrTop, new Thickness(0, _bdrThickness.Top, 0, 0)) 7 ApplyBorder(bdr, _bdrRight, new Thickness(0, 0, _bdrThickness.Right, 0)) 8 ApplyBorder(bdr, _bdrBottom, new Thickness(0, 0, 0, _bdrThickness.Bottom)) 9 } 10 void ApplyBorder(Border bdr, Brush br, Thickness t) 11 { 12 if (br != null && t != _thicknessEmpty) 13 { 14 // create inner border 15 var inner = new Border() 16 inner.BorderThickness = t 17 inner.BorderBrush = br 18 19 // transfer content 20 var content = bdr.Child 21 bdr.Child = inner 22 inner.Child = content 23 24 // transfer padding 25 inner.Padding = bdr.Padding 26 bdr.Padding = _thicknessEmpty 27 } 28 } 29
ExcelCellStyle
楼主就照这个思路进行优化,每个单元格有一个默认的Border——bdr,让它负责处理C1FlexGrid默认的条条框框显示,即在一中提及的灰色线条;然后再嵌套两层Border,一个负责右边框,一个负责下边框,理由是为了不让重叠的边框显示成粗线条,令所有单元格都只负责处理其右边框和下边框,并将该单元格的上边框交由它上面那个单元格的下边框负责,该单元格的左边框交由它左侧那个单元格的右边框负责,这样达成一致后,就可以避免相邻单元格中间出现粗线条的现象。
三 优化实现
在自定义的CellStyle中定义自己的单元格边框设置,如下
private Thickness _bdrThickness;// 单元格边框
然后在自动应用单元格样式的方法Apply中实现优化:
1 /// <summary> 2 /// 重绘单元格时,嵌套两层Border用来分别显示右边框和下边框 3 /// </summary> 4 public override void Apply(Border bdr, SelectedState selState) 5 { 6 base.Apply(bdr, selState) 7 8 // 下边框 9 Border bottom = new Border() 10 bottom.BorderThickness = new Thickness(0, 0, 0, 1) 11 bottom.BorderBrush = _bdrThickness.Bottom == 1 12 ? new SolidColorBrush(Colors.Black) 13 : new SolidColorBrush(Color.FromArgb(0xff, 0xe7, 0xe7, 0xe7)) 14 15 // 右边框 16 Border right = new Border() 17 right.BorderThickness = new Thickness(0, 0, 1, 0) 18 right.BorderBrush = _bdrThickness.Right == 1 19 ? new SolidColorBrush(Colors.Black) 20 : new SolidColorBrush(Color.FromArgb(0xff, 0xe7, 0xe7, 0xe7)) 21 22 // 左边框和上边框放在最外面的主边框进行设置 23 if (_bdrThickness.Left == 1 || _bdrThickness.Top == 1) 24 { 25 bdr.BorderBrush = new SolidColorBrush(Colors.Black) 26 bdr.BorderThickness = new Thickness(_bdrThickness.Left, _bdrThickness.Top, 0, 0) 27 } 28 else 29 { 30 bdr.BorderThickness = new Thickness(0, 0, 0, 0) 31 } 32 33 UIElement content = bdr.Child 34 bdr.Child = bottom 35 bottom.Child = right 36 right.Child = content 37 38 right.Padding = bdr.Padding 39 bottom.Padding = _thicknessEmpty 40 bdr.Padding = _thicknessEmpty 41 } 42
最后在C1FlexGrid的CellFactory中应用单元格样式时,就取在CellStyle中自己定义的单元格边框_bdrThickness值作为Border的边框值即可。
当然了,对C1FlexGrid的单元格边框优化完成之后,对于在设置单元格边框时是有一条原则的,就是如果设置该单元格的右边框和下边框,那好办,直接设置该单元格的_bdrThickness属性即可;但是如果设置该单元的左边框和上边框,就要交给对应的单元格对应的边框进行处理。
好了,最后看一下楼主将优化方案放进仿Excel扩展C1FlexGrid控件的效果吧。
这套优化方案是根据Demo里的启发实现的,楼主在这之前还有一套自己的优化方案,可见楼主有多闲的dt了,以后有时间了再把那套方案放进来。
四 资源下载
仿Excel扩展C1FlexGrid控件: http://files.cnblogs.com/files/memento/Memento.SLExcelSample.zip
(工程里已经加入上一篇文章实现的行列增删以及单元格的合并拆分功能)
请多指教,谢谢!