FlexGrid for WPF 帮助文档
自定义单元格

如果你现在运行这个示例,grid已经工作并按照期望更新数据。您可以更改更新参数以使其更或更少的频繁,在更新过程中滚动grid,等等。
然而,虽然更新正在发生,他们很难理解。有太多的数字在屏幕上随机位置刷新。

自定义单元格通过闪烁以及sparkline提供了一个更好的用户体验。

当单元格包含的值发生改变时,闪烁动画将临时地改变单元格的背景。如果一个数值增加,该单元格将在瞬间变成绿色,然后逐渐的变淡,直至恢复成白色。

Sparkline是显示在每一个单元格中的微型图表。该微型图表展示了该单元格的最后五个值,因此用户可以立即识别出数值变化的趋势(该值在上升,下降,或者持平)。

要使用自定义单元格,我们继续在上一示例中进行修改。我们首先从创建一个FinancialCellFactory类并指定该类的一个实例至grid的CellFactory属性开始。

C#
拷贝代码
// 使用自定义单元格工厂
_flexFinancial.CellFactory = new FinancialCellFactory();
// 自定义单元格工厂定义
public class FinancialCellFactory : CellFactory{
  public override void CreateCellContent(C1FlexGrid grid, Border bdr, CellRange range)  
{
    // 获取单元格信息
    var r = grid.Rows[range.Row];
    var c = grid.Columns[range.Column];
    var pi = c.PropertyInfo;
    // 检查这是一个我们期望的单元格 
    if (r.DataItem is FinancialData && (pi.Name == "LastSale" || pi.Name == "Bid" || pi.Name == "Ask"))    
   {
      // 创建 StockTicker 元素并添加至单元格
      var ticker = new StockTicker();
      bdr.Child = ticker;     
     // 绑定StockTicker 至该行的FinancialData 对象
      var binding = new Binding(pi.Name);
      binding.Source = r.DataItem;
      binding.Mode = BindingMode.OneWay;
      ticker.SetBinding(StockTicker.ValueProperty, binding);     
     // 添加一些信息至 StockTicker 元素
      ticker.Tag = r.DataItem;
      ticker.BindingSource = pi.Name;    }
    else
    {
      // 使用默认实现
      base.CreateCellContent(grid, bdr, range);    }  }
}

我们的自定义单元格工厂首先检查该行的数据是否是FinancialData,并且该列是否绑定到数据对象的LastSale, Bid, 或者 Ask属性。如果所有这些条件都满足,单元格工厂将创建一个新的StockTicker元素并绑定到数据。

StockTicker元素将数据显示给用户。它由一个包含以下子元素的四列的Grid元素组成:

元素描述 类型 名称
当前值 TextBlock _txtValue
最后变化的百分比 TextBlock _txtChange
上/下图标 Polygon _arrow
Sparkline Polyline _sparkLine

这些元素在StockTicker.xaml文件中定义,我们这里不列举完整的清单。

StockTicker.xaml文件中最有趣的部分是用来实现闪烁行为脚本的定义。Storyboard逐渐地改变控件的背景色从当前值至透明:

XAML
拷贝代码
<UserControl.Resources>  <Storyboard x:Key="_sbFlash" >    <ColorAnimation      Storyboard.TargetName="_root"      Storyboard.TargetProperty=               "(Grid.Background).(SolidColorBrush.Color)"      To="Transparent"      Duration="0:0:1"    />  </Storyboard></UserControl.Resources>

StockTicker的实现代码包含在StockTicker.cs 文件中。有趣的部分注释如下:

C#
拷贝代码
/// <summary>
/// Interaction logic for StockTicker.xaml
/// </summary>
public partial class StockTicker : UserControl
{
  public static readonly DependencyProperty ValueProperty = 
    DependencyProperty.Register(
      "Value", 
      typeof(double), 
      typeof(StockTicker), 
      new PropertyMetadata(0.0, ValueChanged));

我们从定义一个叫做ValueProperty的DependencyProperty开始,该属性将被用作绑定底层的数据值。Value属性实现如下:

C#
拷贝代码
public double Value
{
  get { return (double)GetValue(ValueProperty); }
  set { SetValue(ValueProperty, value); }
}
private static void ValueChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
{
  var ticker = d as StockTicker;
  var value = (double)e.NewValue;
  var oldValue = (double)e.OldValue;

为了实现sparkline,控件需要访问除了当前值和上一个值之外更多的值。这将通过在控件的Tag属性保存FinancialData对象完成,接下来调用FinancialData.GetHistory方法。

实际上,由事件的OldValue属性提供的前一个数值在这种情况下无论如何是靠不住的。这是由于grid将虚拟化显示单元格,StockTicker.Value可能会发生变化,因为控件由于滚动到可见区域刚刚被创建。在这种情况下,控件没有以前的值。从FinancialData对象获取之前的值也需要考虑这个问题。

C#
拷贝代码
  // 获取历史数据
  var data = ticker.Tag as FinancialData;
  var list = data.GetHistory(ticker.BindingSource);
  if (list != null && list.Count > 1)
  {
    oldValue = (double)list[list.Count - 2];
  }

一旦这些值可用,控件将计算以百分比表示的上一次改变的变化率,并更新控件文本:

C#
拷贝代码
  // 计算以百分比表示的变化率
  var change = oldValue == 0 || double.IsNaN(oldValue)
    ? 0
    : (value - oldValue) / oldValue;

  // 更新文本
  ticker._txtValue.Text = value.ToString(ticker._format);

百分比表示的变化率也用来更新up/down符号以及文本和闪烁的颜色。如果没有变化,则该up/down符号将被隐藏,并且文本被设置为默认颜色。
如果变化是负向的,则代码将通过设置其ScaleY变换为-1,使得up/down符号向下显示,同时设置符号的颜色,以及闪烁动画的颜色为红色。
如果变化是正向的,则代码将通过设置其ScaleY变换为+1,使得up/down符号向上显示,同时设置符号的颜色,以及闪烁动画的颜色为绿色。

C#
拷贝代码
  // 更新符号和闪烁动画的颜色
  var ca = ticker._flash.Children[0] as ColorAnimation;
  if (change == 0)
  {
    ticker._arrow.Fill = null;
    ticker._txtChange.Foreground = ticker._txtValue.Foreground;
  }
  else if (change < 0)
  {
    ticker._stArrow.ScaleY = -1;
    ticker._txtChange.Foreground = ticker._arrow.Fill = _brNegative;
    ca.From = _clrNegative;
  }
  else
  {
    ticker._stArrow.ScaleY = +1;
    ticker._txtChange.Foreground = ticker._arrow.Fill = _brPositive;
    ca.From = _clrPositive;
  }

下一步,代码通过使用由早先调用FinancialData.GetHistory方法提供的历史值数组更新sparkline多边形的Points属性,以更新sparkline。sparkline的Stretch属性被设置为Fill,因此线形将自动缩放以适应可用的空间大小。

C#
拷贝代码
  // 更新sparkline
  if (list != null)
  {
    var points = ticker._sparkLine.Points;
    points.Clear();
    for (int x = 0; x < list.Count; x++)
    {
      points.Add(new Point(x, (double)list[x]));
    }
  }

最后,如果值真的发生了变化,而且控件不是刚刚被创建,则代码通过调用StoryBoard.Begin方法闪烁单元格

C#
拷贝代码
  // 闪烁新值(但是不能是控件创建之后立刻就刷新)
  if (!ticker._firstTime)
  {
    ticker._flash.Begin();
  }
  ticker._firstTime = false;
}

总结一下StockTicker控件。如果您运行该示例应用程序,并选择“自定义单元格”复选框,您将立即看到一个具有更多信息显示的界面,单元格将在数值发生变化时闪烁显示,同时sparkline提供一个关于数值变化趋势的快速指示。

查看其它

 

 


产品网站:http://www.gcpowertools.com.cn  |  咨询热线:4006576008   |   ©2015 西安葡萄城