[Silverlight] 分离C1FlexGrid滚动条

一  场景介绍

Silverlight 5.0的C1FlexGrid控件里自带的滚动条,是嵌入在C1FlexGrid宽度和高度的范围里的,效果如下图所示:

(未隐藏自带滚动条)     (隐藏自带的滚动条)

其中行高的定义如下:

<c1:C1FlexGrid x:Name="flxg" Width="300" Height="200"
               Grid.Row="0" HeadersVisibility="None"
               AlternatingRowBackground="AliceBlue" Background="LightGray"
               GridLinesVisibility="All" GridLinesBrush="Black">
    <c1:C1FlexGrid.Rows>
        <c1:Row Height="100" />
        <c1:Row Height="100" />
    </c1:C1FlexGrid.Rows>
    <c1:C1FlexGrid.Columns>
        <c1:Column Width="100" />
        <c1:Column Width="100" />
        <c1:Column Width="100" />
    </c1:C1FlexGrid.Columns>
</c1:C1FlexGrid>

即使把C1FlexGrid的行、宽设置成所有 行高和 或所有 列宽和,自带的滚动条还是会显示出来,但实际上如果隐藏掉C1FlexGrid自带的滚动条,效果就好看多了,所以我就想把C1FlexGrid自带的滚动条隐藏掉,然后在下方或右侧加一个自己的滚动条,来操作滚动C1FlexGrid。

二  解决思路

1、C1FlexGrid的属性ScrollPosition可以获取或设置其自带的滚动条的偏移量;

2、C1FlexGrid中与滚动有关的事件有,ScrollPositionChanging和ScrollPositionChanged,断点调试实验一下即可知道当执行到ScrollPositionChanged事件时,C1FlexGrid的ScrollPosition属性值更新为滚动条的偏移量;

3、当C1FlexGrid触发ScrollPositionChanged事件时,更新自定义滚动条(ScrollBar)的偏移值;自定义滚动条(ScrollBar)的ValueChanged事件触发时,更新C1FlexGrid的ScrollPosition属性值;

4、注意C1FlexGrid的ScrollPosition属性为负,ScrollBar的Value属性值为正,注意正负转换;

5、ScrollBar的Maximum属性:设置滚动条可滑动的最大值,应等于C1FlexGrid可视范围之外的长度或宽度值;

6、ScrollBar的ViewportSize属性:设置滚动条上白条的长度值,应该等于C1FlexGrid的宽度值,即可视范围的长度或宽度值;

三  部分代码

根据C1FlexGrid初始化滚动条

  1 /// <summary>
  2 /// 根据C1FlexGrid初始化滚动条
  3 /// </summary>
  4 /// <param name="flexGrid"></param>
  5 private void InitScrollbar(C1FlexGrid flexGrid)
  6 {
  7 	double allColumnsWidth = 0;
  8 	double allRowsHeight = 0;
  9 	foreach (Column col in flexGrid.Columns)
 10 	{
 11 		allColumnsWidth += col.Width.Value;
 12 	}
 13 	foreach (Row row in flexGrid.Rows)
 14 	{
 15 		allRowsHeight += row.Height;
 16 	}
 17 	// 当所有行高和大于C1FlexGrid框的高度,则纵向滚动条可用
 18 	if (allRowsHeight > flexGrid.Height)
 19 	{
 20 		scrollbarVert.Visibility = Visibility.Visible;
 21 		// 纵向滚动条的最大值应该是C1FlexGrid中超出可见范围剩余的高度
 22 		scrollbarVert.Maximum = allRowsHeight - flexGrid.Height;
 23 		// 滚动条上白条的长度应该是C1FlexGrid可见范围的高度
 24 		scrollbarVert.ViewportSize = flexGrid.Height;
 25 		scrollbarHori.SmallChange = 1;// 滚动改变的最小值
 26 	}
 27 	else
 28 	{
 29 		scrollbarVert.Visibility = Visibility.Collapsed;
 30 	}
 31 	// 当所有列宽和大于C1FlexGrid框的宽度,则横向滚动条可用
 32 	if (allColumnsWidth > flexGrid.Width)
 33 	{
 34 		scrollbarHori.Visibility = Visibility.Visible;
 35 		// 横向滚动条的最大值应该是C1FlexGrid中超出可见范围剩余的宽度
 36 		scrollbarHori.Maximum = allColumnsWidth - flexGrid.Width;
 37 		// 滚动条上白条的长度应该是C1FlexGrid可见范围的宽度
 38 		scrollbarHori.ViewportSize = flexGrid.Width;
 39 		scrollbarHori.SmallChange = 1;// 滚动改变的最小值
 40 	}
 41 	else
 42 	{
 43 		scrollbarHori.Visibility = Visibility.Collapsed;
 44 	}
 45 }

C1FlexGrid触发滚动事件

  1 // C1FlexGrid的滚动事件
  2 private void flxg_ScrollPositionChanged(object sender, EventArgs e)
  3 {
  4 	Point position = flxg.ScrollPosition;// C1FlexGrid当前滚动条的位置
  5 	txtMsg1.Text = "C1FlexGrid: " + position.X + "," + position.Y;
  6 	// 更新自定义滚动条
  7 	scrollbarHori.Value = -position.X;
  8 	scrollbarVert.Value = -position.Y;
  9 }

横/纵滚动条滑动事件

  1 // 横向滚动条
  2 private void scrollbarHori_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
  3 {
  4 	// 注意,滚动条控件Scrollbar的value值是正数,与C1FlexGrid的滚动条位置正好相反
  5 	flxg.ScrollPosition = new Point(-scrollbarHori.Value, flxg.ScrollPosition.Y);
  6 }
  7
  8 // 纵向滚动条
  9 private void scrollbarVert_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
 10 {
 11 	// 注意,滚动条控件Scrollbar的value值是正数,与C1FlexGrid的滚动条位置正好相反
 12 	flxg.ScrollPosition = new Point(flxg.ScrollPosition.X, -scrollbarVert.Value);
 13 }

四  后话

C1FlexGrid在ScrollBar部分我觉得做的并不精致,当把C1FlexGrid的长、宽设置成完全等于所有行高和、所有列宽和时,如上面所说C1FlexGrid自带的滚动条会显示出来,如果这时候要完全显示C1FlexGrid右下角那个单元格时,滚动条的偏移量为(-3,-3);

所以如果按照我上面的代码执行,然后再把自定义的两个滚动条拉到最下面或最右侧,此时C1FlexGrid的滚动条偏移量还差3,如下图所示:

滚动条拉到极端时偏移量显示为(-200,-150)

最后一个单元格完全显示时,偏移量显示为(-203,-153)

所以实际上在给自定义滚动条ScrollBar设置最大偏移值时,应另外加3,即scrollbarVert.Maximum = allRowsHeight - flexGrid.Height + 3;

这样就完全同步了;

五  资源下载

源代码Sample工程下载 http://files.cnblogs.com/files/memento/SLC1FlexGridScorllbar.2015.03.20.zip

时间: 2025-01-04 10:28:42

[Silverlight] 分离C1FlexGrid滚动条的相关文章

[Silverlight] 实现C1FlexGrid撤销还原功能

采用设计模式中的"命令模式"实现C1FlexGrid的撤销还原功能,那就先从命令模式简单介绍开始吧. 一  命令模式 命令模式属于对象的行为型模式,将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销还原的操作. 采用命令模式,把发出命令的责任和执行命令的责任分隔开,委派给不同的对象.ICommand是命令的接口,指定所有命令必须实现两个方法Execute(执行,还原)和Undo(撤销):ConcreteCommand作为具体命令

[Silverlight] 优化C1FlexGrid单元格边框

一  优化理由 如下图所示,如果按照C1FlexGrid自带的单元格边框设置,即对每个单元格的CellStyle的BorderThickness进行设置,会得到如下图的效果: 其中,明显可以看到如果两个相邻的单元格同时设置了那条相邻的边,则会看起来很粗--原因很简单,C1FlexGrid是在Grid的基础上扩展,并且对每个单元格的绘制都是通过嵌套一层Border处理的,然后楼主就闲着dt自己用Grid模拟了一个简单的C1FlexGrid表格,然后用Border嵌套放入,设置了一下Border的边

[Silverlight] 仿Excel扩展C1FlexGrid控件

一  分析阶段 根据Excel表格区域的划分,如下图,基本上以4行*3列的框架搭建: 第一行为列头区域     ==>  C1FlexGrid.ColumnHeaders 第二行为单元格区域  ==>  C1FlexGrid.Cells 第三行为列尾区域     ==>  C1FlexGrid.ColumnFooters 第四行为横向滚动条区域,在Excel里还有工作簿页签等: 第一列为行头区域     ==>  C1FlexGrid.RowHeaders 第二列为单元格区域 第三

如何去掉Silverlight应用程序在浏览器中的滚动条

问题: 解决: 打开承载Silverlight应用程序的.aspx或者.html文件,如图: OK,烦人的滚动条消失~~~~

Silverlight CheckBox 滚动条BUG + 详解

在SL项目中 做复选框 我的做法是通过DataGrid或者ListBox 配合CheckBox 绑定数据源生成ListBoxItem 数据源是用ADO.NET EF6.0生成的实体模型 然后就遇到了一个SL3的时候就存在的BUG 当ListBox中的项太多,控件自动会添加滚动条,这时候随便拖动滚动条以后就会发现,一些没有被勾选的CheckBox会变成IsChecked状态 进过查阅资料以后得知是微软在UI本身的BUG,这种BUG不会影响后台的数据,但是影响了使用 解决方法有两种 方法1.绑定Ch

企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(3)

第一章 表现模式关注分离(soc)是企业及软件开发中非常有用的核心原则,也是许多表现模式背后的驱动力量.在WPF和Silverlight开发中,MVVM成为了实现关注分离最为有效的设计模式.然而,这种模式与其他表现模式(MVC,MVP)相比实现起来相对困难.本章会以贯穿全书的账票项目的例子作为开始.在回顾表现模式的过程中,用每一种模式来实现账票项目使你更加明确它们的优劣所在,这会帮助你明白为什么要使用MVVM模式.账票项目应用例子我们从账票项目的基本功能入手,账票项目应用的UI如下所示: 当pr

Silverlight中使用MVVM(4)—演练

本来打算用MVVM实现CRUD操作的,这方面例子网上资源还挺多的,毕竟CRUD算是基本功了,因为最近已经开始学习Cailburn框架了,感觉时间 挺紧的,这篇就实现其中的更新操作吧.         功能很明确,当我们更改DataGrid中的CheckBox时,将源中当前发生变化的数据项在界面上显示出来.我们仍然在前面项目的基础上实现这个功能 首先我们需要给实体Person类添加一个Bool的属性,因为这里我们只对这个属性值操作,所以对于age,name属性也就无必要实现更改通知了 public

Silverlight中使用MVVM(2)-(提高)

在第一篇文章中的示例中,我们已经简单的了解了应用MVVM模式的流程,我的本意是你已经了解了一点MVVM的概念,然后又没有一个较好的例子学习,可以跟着我一起学习MVVM模式,所以这个部分,都是没有理论知识的,当然整个例子学完后,我们会回过头探讨一下,将其总结出来. 现 在我们主要在前面的示例上进行扩展,前面的示例中我们主要是将一个源对象绑定到DataGrid中的,接下来我们继续使用MVVM模式,将 DataGrid选择行的变化体现界面中,其实通过这个需求变化,你会发现UI与逻辑分离带来的优势,尽管

Silverlight中使用MVVM(3)—进阶

这篇主要引申出Command结合MVVM模式在应用程序中的使用 我们要做出的效果是这样的 就是提供了一个简单的查询功能将结果绑定到DataGrid中,在前面的基础上,这个部分相对比较容易实现了 我们在PageViewModel中添加两个属性 private string _searchText; //查询关键字 public string SearchText { get { return _searchText; } set { _searchText = value; if (Propert