FlexGrid for WPF对表格数据选择的几种模式

作者:控件中国网   出处:控件中国网   2015-10-29 15:03:47   阅读:8

Silverlight及WPF版C1FlexGrid控件在相关的ComponentOne StudioV2 2010发布版中引入,自那时以来,该控件已经得到大幅改善。这篇文章主要介绍C1FlexGrid的选择和选择模式,除了以表格形式显示数据外,大多数grid控件允许用户使用鼠标和键盘选择数据的一部分。C1FlexGrid具有丰富的选择模型,由SelectionMode属性进行控制。以下选择模式可用:
  • Cell: 选择对应单个单元格。
  • CellRange: 选择对应于一个单元格区域(相邻单元格的一块区域)。
  • Row: 选择对应于一个整行。
  • RowRange: 选择对应于一段连续的整行。
  • ListBox: 选择对应于一组行(不一定是连续的)
默认的SelectionMode是CellRange,提供了一个用户熟悉的,类似于Excel操作风格的选择行为。基于行进行选择的选项在需要选择整个数据行而不是单个Grid单元格的场景下同样有用。无论当前的选择模式是什么,Grid都通过Selection属性暴露了当前的选择。此属性获取或设置当前的选择作为一个CellRange的对象。
1、监控选择
一旦选择发生变化,可以是由于用户操作或者代码修改所引起,Grid将触发SelectionChanged事件,允许您处理新的选择结果。例如,下面的代码可以监视选择并在选择更改时发送信息到控制台:
void _flex_SelectionChanged(object sender, CellRangeEventArgs e)
{
 CellRange sel = _flex.Selection;
 Console.WriteLine("selection: {0},{1} - {2},{3}",
 sel.Row, sel.Column, sel.Row2, sel.Column2);
 Console.WriteLine("selection content: {0}",
 GetClipString(_flex, sel));
}
static string GetClipString(C1FlexGrid fg, CellRange sel)
{
 var sb = new System.Text.StringBuilder();
for (int r = sel.TopRow; r <= sel.BottomRow; r++)
 {
 for (int c = sel.LeftColumn; c <= sel.RightColumn; c++)
 {
 sb.AppendFormat("{0}\t", fg[r, c].ToString());
 }
 sb.AppendLine();
 }
 return sb.ToString();
}
一旦选择发生变化,代码将列举表示当前选择的CellRange的坐标。同时它还使用GetClipString方法输出选择范围的内容,该方法遍历选择的项目并使用Grid的索引获取选择范围中每一个单元格的内容
 
请注意,GetClipString方法中的for循环使用单元格的TopRow,ButtomRow,LeftColumn以及RightColumn苏醒,而不是Row,Row2,Column以及Column2属性。这是必须的,因为Row可能大于或者小于Row2,取决于用户如何执行该选择(在选择时向上或者向下拖拽鼠标)。您可以很容易地通过Rows.GetDataItems方法从Selection中抽取大量有用的信息。该方法返回一个关联到一个CellRange的数据项的集合。一旦你有了这个集合,你可以使用LINQ进行提炼和总结有关选定项目的信息。例如,可以考虑为一个绑定到Customer对象集合的Grid使用以下SelectionChanged事件处理的替代方案:
void _flex_SelectionChanged(object sender, CellRangeEventArgs e)
{
 // 获取选定范围内的客户对象
var customers =
 _flex.Rows.GetDataItems(_flex.Selection).OfType<Customer>();
// 使用LINQ从选中的客户对象集合中抽取信息
 _lblSelState.Text = string.Format(
 "{0} items selected, {1} active, total weight: {2:n2}",
 customers.Count(),
 (from c in customers where c.Active select c).Count(),
 (from c in customers select c.Weight).Sum());
}
注意,该代码使用OfType运算符将选中的数据项转换为Customer类型。一旦该步骤完成,代码将使用LINQ获取一个总数,一个“active”状态的客户数,以及选中客户的总权重。LINQ是完成这类工作的完美工具。它是灵活,富有表现力的,紧凑而且高效。
2、通过代码选择单元格和对象
Selection属性是可读写的,所以你可以使用代码选择单元格范围。您还可以使用Select方法进行选择,就像在WinForms版本的C1FlexGrid控件那样。Select方法允许您选择单元格或范围,并可选地滚动新的选择范围到可视视图,以便用户可以看到它。例如,为了选中Grid的第一个单元格并确保它位于用户可见范围,应使用以下代码:
 
// 选择第零行,第零列,并确保该单元格可见
fg.Select(0, 0, true);
选择相关的方法均基于行和列的索引进行工作。但是您也可以用来基于单元格内容进行选择。例如,以下代码选择在Grid的“Name”列中,第一个包含指定字符串的行。
bool SelectName(string name)
{
 // 在“Name”列查找包含指定字符串的行
int col = _flexGroup.Columns["Name"].Index;
int row = FindRow(_flex, name, _flex.Selection.Row, col, true);
if (row > -1)
 {
 _flex.Select(row, col);
 return true;
 }
 // 未查询到…… 
return false;
}
该代码使用的FindRow辅助方法定义如下:
// 在一个指定的列中查找包含某个文本的行
int FindRow(C1FlexGrid flex, string text,
 int startRow, int col, bool wrap)
{
 int count = flex.Rows.Count;
for (int off = 0; off <= count; off++)
 {
 // 搜索到底部且不允许循环查找?立即退出
if (!wrap && startRow + off >= count)
 {
 break;
 }
 // 从行中获取文本
int row = (startRow + off) % count;
var content = flex[row, col];
// 如果查找到匹配项则返回匹配行的索引
if (content != null &&
 content.ToString().IndexOf(text,
 StringComparison.OrdinalIgnoreCase) > -1)
 {
 return row;
 }
 }
 // 未查询到…… 
return -1;
}
该FindRow方法实现了在C1FlexGrid的WinForms版本中提供的FindRow方法的功能。此方法没有内置在Silverlight或WPF版本的Grid产品中,以使得控件所占用的尺寸尽可能的小。该方法在给定的列中搜索指定的字符串,从指定的行开始搜索,并可选地在搜索到末尾仍未查找到时返回到行首开始搜索。这在许多场景下已经具有足够的使用灵活性。另一个常见的选择场景是在数据源中选择一个特定对象的情况。你的第一反应可能会查找并使用PagedCollectionView.IndexOf 方法从数据源集合中查找对象的索引,然后使用索引选择行。这种方法的问题是,它
只有在数据没有进行分组时能够正常工作。如果已经将数据进行了分组,则分组行也将进行计数,这将导致数据源中的项目的索引和Grid中的行索引不匹配。解决这种问题的最简单的方式是枚举每一行,并将您搜索的项目和每一行的DataItem属性进行比较。下面的代码演示
了如何做到这一点:
 
var customer = GetSomeCustomer;
#if false // ** 千万不要使用这种方式,因为它将在存在分组的情况下无法正常工作
 int index = view.IndexOf(customer);
if (index > -1)
 {
 _flex.Select(index, 0);
 }
#else // 这是在Grid中搜索对象的安全方式
 for (int row = 0; row <= _flex.Rows.Count; row++)
 {
 if (row.DataItem == customer)
 {
 _flex.Select(row, 0);
 }
 }
#endif
3、自定义选择显示
C1FlexGrid提供两种功能,允许您自定义选择高亮显示给最终用户的方式。
Excel-风格的Marquee
如果您设置了ShowMarquee属性的值为True,Grid将在选择区域自动绘制一个矩形框,使得非常容易的可以发现选择区域。默认情况下,Marquee是一个两个像素宽的黑色矩形框,但是您可以通过Marquee属性对其进行定制。
选中的单元格Header
如果您指定了自定义的画刷对象至Grid的ColumnHeaderSelectedBackground以及RowHeaderSelectedBackground属性,则Grid将高亮显示关联到选中单元格的Header,使得最终用户可以非常容易地确认包含选择区域的行和列的位置。将这些属性综合在一起使用,使得您可以实现一个具有熟悉的Excel外观和使用习惯的Grid。
Copyright© 2006-2015 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 渝ICP备12000264号 法律顾问:元炳律师事务所
客服软件
live chat