Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

CellStyle cs = _flex.Styles.Add("Fifth"); cs.BackColor = Color.Gray; for (int index = _flex.Rows.Fixed ; index <= _flex.Rows.Count - 1; index += 5)
{

Wiki Markup
_flex.Rows\[index\].Style = cs;


下面是一个例子,显示了如何创建自定义样式,并将它们分配到行,列和单元格区域:

...

' 创建一个新的自定义样式。
Dim s As CellStyle = _flex.Styles.Add("MyStyle") s.BackColor = Color.Red
s.ForeColor = Color.White
' 将新的样式分配到一列。
_flex.Cols(3).Style = _flex.Styles("MyStyle")
' 将新的样式分配到一行。
_flex.Rows(3).Style = _flex.Styles("MyStyle")
' 将新的样式分配到一个单元格区域。
Dim rg As CellRange = _flex.GetCellRange(4, 4, 6, 6) rg.Style = _flex.Styles("MyStyle")
 C#
// 创建一个新的自定义样式。
CellStyle s = _flex.Styles.Add("MyStyle"); s.BackColor = Color.Red;
s.ForeColor = Color.White;
// 将新的样式分配到一列。

Wiki Markup
_flex.Cols\[3\].Style = _flex.Styles\["MyStyle"\];


// 将新的样式分配到一行。


Wiki Markup
_flex.Rows\[3\].Style = _flex.Styles\["MyStyle"\];



// 将新的样式分配到一个单元格区域。


Wiki Markup
CellRange rg = _flex.GetCellRange(4,4,6,6);  rg.Style = _flex.Styles\["MyStyle"\];



只要你愿意,你就可以在设计时使用 C1FlexGrid 样式编辑器来设置好样

...

  • Visual Basic

    Dim cs As C1.Win.C1FlexGrid.CellStyle
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ' 为"大货币值"创建一个自定义样式。
    cs = _flex.Styles.Add("LargeValue") cs.Font = New Font(Font, FontStyle.Italic) cs.BackColor = Color.Gold End Sub
    ' 根据单元格的内容来设置其格式。
    Private Sub _flex_CellChanged(ByVal sender As Object, ByVal e As
    RowColEventArgs) Handles _flex.CellChanged
    ' 将货币值大于 50,000 的标记为"大货币值"(通过将"样式"设置为 "无"来重新设置其他的)。
    Dim cs As CellStyle
    If _flex(e.Row, e.Col).ToString >= 50000 Then cs = _flex.Styles("LargeValue")
    _flex.SetCellStyle(e.Row, e.Col, cs)
    End If


  • C#

    CellStyle cs; private void Form1_Load(object sender, EventArgs e)
    {
    // 为大货币值创建一个自定义样式。
    cs = _flex.Styles.Add("LargeValue"); cs.Font = new Font(Font, FontStyle.Italic); cs.BackColor = Color.Gold;
    }
    // 根据单元格的内容来设置其格式。
    private void _flex_CellChanged( object sender, RowColEventArgs e)
    {
    // 将货币值大于 50,000 的标记为"大货币值"(通过将"样式"设置为
    "无"来重新设置其他的)。 if

    Wiki Markup
    (Microsoft.VisualBasic.CompilerServices.Conversions.ToDouble(_flex\[e.Row,  e.Col\].ToString()) >= 50000)


    {


    Wiki Markup
    cs = _flex.Styles\["LargeValue"\];



    _flex.SetCellStyle(e.Row, e.Col, cs);
    }



    自绘单元格


    Wiki Markup
    即使 "单元格样式"对象已经通过单元格外观(背景色和前景色、对齐方式、字体、边距、边框,等等)提供了很多控件,有时这仍是不够的。你可能想使用渐变背景,或直接在单元格中画一些自定义的图形。在这些情况下,你可以使用"绘制模式"属性和"自绘单元格"事件,通过每一个单元格是如何绘制的来实现全面控制。 
    "绘制模式"属性决定了 "自绘单元格"事件是否被激发。该事件可以是你兼顾到每一个单元格的视觉效果。"自绘单元格"事件中的参数,允许你对所显示的数据以及用于显示数据的样式,做出更改,甚至允许你完全接管并绘制单元格中你所想要的任何东西。 
    你可以通过在事件处理程序中设置 e.Text 和 e.Image 参数,来改变即将显示在单元格中的文本和图像。你也可以通过设置 e.Style 属性来改变将用于显示单元格的样式。请注意,你不应该修改样式参数的属性,因为这可能会影响到其他单元格。相反,你要分配一个新的"{*}单元格样式{*}"对象到"样式"参数。
    例如,不要设置 *e.Style.ForeColor= Color.Red{*},而应该通过使用 *e.Style =* 
    *_flex.Styles\["RedStyle"\]{*}将一个全新的样式分配给参数。 
    你还可以使用自己的绘图代码在单元格中进行绘制,甚至用命令将你的自定义代码与 *e.DrawCell* 方法合并到一起。例如,你可以使用 GDI 命令来绘制单元格的背景,然后调用 *e.DrawCell* 来显示单元格边框和内容。 
    可用的示例项目 
    有关高级的{*}自绘单元格{*}的一个范例,请参阅"ComponentOne 帮助中心" 的 *RtfGrid* 样品。 
    下面的代码显示了一个例子。它使用了渐变画笔来绘制所选定的单元格的背景。首先,代码会设置"绘制模式"属性,显示一个"{*}线性渐变画笔{*}"的对象并且在表格重新调整大小时更新画笔:
     \\
     Visual Basic  
    <span style="color: #1f497d">Dim m_GradientBrush As System.Drawing.Drawing2D.LinearGradientBrush</span>  
    <span style="color: #1f497d">Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As  System.EventArgs) Handles MyBase.Load</span>  
    <span style="color: #1f497d">' 通过自绘单元格来使用画笔。</span>  
    <span style="color: #1f497d">m_GradientBrush = New</span>  
    <span style="color: #1f497d">System.Drawing.Drawing2D.LinearGradientBrush(ClientRectangle,  Color.SteelBlue, Color.White, 45)</span>  
    <span style="color: #1f497d">' 使用自绘来添加渐变。</span>  
    <span style="color: #1f497d">_flex.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw</span>  
    <span style="color: #1f497d">End Sub</span>  
    <span style="color: #1f497d">Private Sub _flex_Resize(ByVal sender As Object, ByVal e As  System.EventArgs) Handles _flex.Resize</span>  
    <span style="color: #1f497d">' 当控件调整大小时更新渐变画笔。</span>  
    <span style="color: #1f497d">m_GradientBrush = New</span>  
    <span style="color: #1f497d">System.Drawing.Drawing2D.LinearGradientBrush(ClientRectangle,</span>  
    <span style="color: #1f497d">Color.SteelBlue, Color.White, 45)</span>  
    <span style="color: #1f497d">End Sub</span>   
     C# 
    <span style="color: #1f497d">System.Drawing.Drawing2D.LinearGradientBrush m_GradientBrush;  private void Form1_Load(object sender, EventArgs e)</span>  
    <span style="color: #1f497d">{</span>  
    <span style="color: #1f497d">// 通过自绘单元格来使用画笔。</span> 
    <span style="color: #1f497d">m_GradientBrush = new</span>  
    <span style="color: #1f497d">System.Drawing.Drawing2D.LinearGradientBrush(ClientRectangle,  Color.SteelBlue, Color.White, 45);</span>  
    <span style="color: #1f497d">// 使用自绘来添加渐变。</span> 
    <span style="color: #1f497d">_flex.DrawMode = DrawModeEnum.OwnerDraw;</span>  
    <span style="color: #1f497d">}</span>  
    <span style="color: #1f497d">private void _flex_Resize( object sender, System.EventArgs e)</span>  
    <span style="color: #1f497d">{</span>  
    <span style="color: #1f497d">// 当控件调整大小时更新渐变画笔。</span> 
    <span style="color: #1f497d">m_GradientBrush = new</span>  
    <span style="color: #1f497d">System.Drawing.Drawing2D.LinearGradientBrush(ClientRectangle,</span>  
    <span style="color: #1f497d">Color.SteelBlue, Color.White, 45);</span>  
    <span style="color: #1f497d">}</span>  
        \\


    第二步是处理"自绘单元格"事件,并使用自定义画刷来绘制单元格的背

    景。在这个例子中,通过在事件参数中使用 "绘制单元格"方法,表格自己处理了自己的前景:
     Visual Basic
    Private Sub _flex_OwnerDrawCell(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.OwnerDrawCellEventArgs) Handles _flex.OwnerDrawCell
    ' 使用渐变画笔来绘制所选定的单元格的背景。
    If _flex.Selection.Contains(e.Row, e.Col) Then
    ' 绘制背景。
    e.Graphics.FillRectangle(m_GradientBrush, e.Bounds)
    ' 让表格绘制其内容。
    e.DrawCell(C1.Win.C1FlexGrid.DrawCellFlags.Content)
    ' 我们已完成这个单元格的绘制。
    e.Handled = True End If
     C#

    private void _flex_OwnerDrawCell( object sender, OwnerDrawCellEventArgs e) {
    // 使用渐变画笔来绘制所选定的单元格的背景。
    if (_flex.Selection.Contains(e.Row, e.Col))
    {
    // 绘制背景。
    e.Graphics.FillRectangle(m_GradientBrush, e.Bounds);
    // 让表格绘制其内容。
    e.DrawCell(DrawCellFlags.Content);
    // 我们已完成这个单元格的绘制。
    e.Handled = true;
    }


    编辑单元格

    默认情况下,C1FlexGrid 控件允许用户通过在单元格中打字来编辑单元格。你可以通过"允许编辑"属性设置为"假"来阻止用户对表格进行编辑。
    你还可以通过将"允许编辑"属性设"假"来阻止用户对特定列进行编辑。
    (当表格被绑定到一个数据源上,它会检测哪些列是可编辑的并自动设置"允许编辑"属性。)
    要开始编辑一个单元格,用户可以:
  • 开始在单元格中输入。这将替换单元格原有的内容。
  • 按 F2 键或 ENTER 键。这使得表格处于编辑模式下,并将当前单元格的内容放到编辑器。
  • 双击一个单元格。这与按 F2 键有相同的效果,但光标会出现在被点击的单元格。

...

' 下拉列表。
_flex.Cols(1).ComboList = "Red|Green|Blue|Red|White"
' 下拉组合。
_flex.Cols(2).ComboList = "|Red|Green|Blue|Red|White"

  • C#

// 下拉列表。

Wiki Markup
_flex.Cols\[1\].ComboList = "Red|Green|Blue|Red|White";


// 下拉组合。


Wiki Markup
_flex.Cols\[2\].ComboList = "|Red|Green|Blue|Red|White";



你也可以在设计时使用"组合列表"对话框来设置"组合列表"属性。
"组合列表"对话框允许你选择你是想让列表显示为一个下拉列表下拉组合省略号按钮,还是文本框省略号按钮

你可以通过"列任务"菜单,或通过 C1FlexGrid 列编辑器来访问"组合列表"对话框。

...

_flex.Cols("bools").Format = "Yes;No"

  • C#


Wiki Markup
_flex.Cols\["bools"\].Format = "Yes;No";



在未绑定模式下,你可以通过使用 GetCellCheck 和 SetCellCheck 属性将复选框添加到任意单元格。复选框将会随着单元格中的任何文本来显示,而且你可以使用列的"图像对齐"属性来设置他们的位置。
复选框有两种类型:布尔和三态。布尔复选框可以在 CheckEnum.Checked 和 CheckEnum.Unchecked 状态之间进行切换。三态复选框可以在
CheckEnum.TSChecked, CheckEnum.TSUnchecked 和 CheckEnum.TSGrayed 之间进行循环切换。
如果某单元格有一个复选框并且"允许编辑"属性被设置为"真",用户可以通过用鼠标点击或按空格键或回车键来改变复选框的状态。
默认情况下,用鼠标或键盘切换复选框的值会将所有选中的复选框都切换掉。你可以通过使用"编辑选项"属性来禁用此功能。

...

System.Collections.Hashtable dtMap = new System.Collections.Hashtable(); dtMap.Add(Color.Red, "Apple"); dtMap.Add(Color.Green, "Forest"); dtMap.Add(Color.Blue, "Sky"); dtMap.Add(Color.Black, "Coal"); dtMap.Add(Color.White, "Snow");

Wiki Markup
_flex.Cols\[1\].DataType = typeof(Color);



Wiki Markup
_flex.Cols\[1\].DataMap = dtMap;



配备了 Idictionary 接口的任何一类都可以作为一个"数据映射"来使用。例如,HashtableListDictionarySortedList 都提供了有效的数据映射。所不同的是,当他们在可编辑的列中使用时,下拉列表中条目的顺序将取决于类。
SortedList 类通过键值将各条目分类,Hashtable 通过任意顺序,而
ListDictionary 保持了那些条目被添加到列表中的顺序。正因为如此,
ListDictionary 通常是"数据映射"的最佳选择。
请注意,当单元格正在编辑中时,数据映射的键值必须是同一类型的。例如,如果一个列包含短整数(Int16),那么,与此列相关联的任何数据映射也应该是短整型的键值。如果将正整数(INT32)作为键值将不起作用。
下面的例子显示了它们的区别:

...

  • Visual Basic

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Load
    ' 按 key 排序。
    Dim sl As New SortedList() sl.Add("0", "Zero") sl.Add("1", "One") sl.Add("2", "Two")
    sl.Add("3", "Three")
    ' 保持添加顺序。
    Dim ld As New Specialized.ListDictionary() ld.Add(0, "Zero") ld.Add(1, "One") ld.Add(2, "Two")
    ld.Add(3, "Three") ' 任意顺序。
    Dim ht As New Hashtable() ht.Add(0, "Zero") ht.Add(1, "One") ht.Add(2, "Two") ht.Add(3, "Three")
    _flex.Cols(1).DataMap = sl
    _flex.Cols(1).Caption = "SortedList"
    _flex.Cols(2).DataMap = ld
    _flex.Cols(2).Caption = "ListDictionary"
    _flex.Cols(3).DataMap = ht
    _flex.Cols(3).Caption = "HashTable"
    End Sub


  • C#

    private void Form1_Load(object sender, System.EventArgs e);
    {
    // 按 key 排序。
    System.Collections.SortedList sl = new System.Collections.SortedList(); sl.Add("0", "Zero"); sl.Add("1", "One"); sl.Add("2", "Two");
    sl.Add("3", "Three"); // 保持添加顺序。
    System.Collections.Specialized.ListDictionary ld = new System.Collections.Specialized.ListDictionary(); ld.Add(0, "Zero"); ld.Add(1, "One"); ld.Add(2, "Two");
    ld.Add(3, "Three");
    // 任意顺序。
    System.Collections.Hashtable ht = new System.Collections.Hashtable(); ht.Add(0, "Zero"); ht.Add(1, "One"); ht.Add(2, "Two"); ht.Add(3, "Three");

    Wiki Markup
    _flex.Cols\[1\].DataMap = sl;



    Wiki Markup
    _flex.Cols\[1\].Caption = "SortedList";




    Wiki Markup
    _flex.Cols\[2\].DataMap = ld;




    Wiki Markup
    _flex.Cols\[2\].Caption = "ListDictionary";




    Wiki Markup
    _flex.Cols\[3\].DataMap = ht;




    Wiki Markup
    _flex.Cols\[3\].Caption = "HashTable";



    }



    此外,如果列的"数据类型"属性被设置为一个枚举,表格将自动建立并使用一个含枚举中每个值的名称的数据映射。例如,下面的代码可以创建一个包含国家的枚举。国家的值存储在表格中,向用户显示的是他们的名字:

  • Visual Basic

Private Enum Countries
NewYork
Chicago
NewOrleans
London
Paris
End Enum
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
_flex.Cols(1).DataType = GetType(Countries) End Sub
 C#
private enum Countries
{
NewYork,
Chicago,
NewOrleans,
London,
Paris
}
private void Form1_Load(object sender, EventArgs e)
{

Wiki Markup
_flex.Cols\[1\].DataType = typeof(Countries);


}


单元格按钮

某些类型的单元格,除了文本框或下拉列表以外,可能还需要更复杂的编辑器。例如,如果一个列包含文件名称或颜色,它应该可以用一个对话框来编辑。
在这些情况下,你应该将 "组合列表"属性设置为省略号("...")。该控件将在单元格旁边显示一个按钮,当用户点击它时,将触发"单元格按钮点击"事件。你可以捕获该事件,显示对话框,并使用用户的选择来更新单元格的内容。
如果你在省略号前添加管道字符,那么用户也将被允许通过在单元格输入的方式来编辑单元格的内容。
默认情况下,单元格的按钮显示省略号。您可以使用"单元格按钮图像" 属性将图片指定到单元格按钮。
下面的示例演示了你应该如何使用单元格按钮来显示一个拾色器对话框,并在一列中选择一种颜色。

...

' 建立色列。
Dim c As C1.Win.C1FlexGrid.Column = _flex.Cols(1) c.DataType = GetType(Color)
' 显示单元格按钮。
c.ComboList = "..."

  • C#

// 建立色列。

Wiki Markup
Column c = _flex.Cols\[1\];


c.DataType = typeof(Color);
// 显示单元格按钮。
c.ComboList = "...";
通过此代码设置该列,用户可以通过点击一个按钮来从一个对话框中选择一个颜色。下一步处理单元格按钮点击的代码:

...

private void _flex_CellButtonClick( object sender, RowColEventArgs e)
{
// 创建"拾色器"对话框。
ColorDialog clrDlg = new ColorDialog();
// 初始化对话框。

Wiki Markup
if (_flex\[e.Row, e.Col\] == typeof(Color))


{


Wiki Markup
clrDlg.Color = (Color)_flex\[e.Row, e.Col\];



}
// 从对话框中获取新的颜色,并将它分配到单元格。
if (clrDlg.ShowDialog() == DialogResult.OK)
{


Wiki Markup
_flex\[e.Row, e.Col\] = clrDlg.Color;



}
}


掩码

C1FlexGrid 控件还支持屏蔽编辑。当用户输入时,这种类型的编辑可以使用一种输入掩码来提供一个模板,并自动验证该输入。该掩码由"编辑掩码" 属性明确指定,它可以通过普通的文本字段和下拉组合区域来使用。
掩码字符串包括两种类型的字符:文字字符,这可以成为输入的一部分;模板字符,这是属于特定类别的占位字符(例如,数字或字母)。例如,下面的代码将一个编辑掩码"(999)999-9999"指定到第一列,该掩码包含的是电话号码,(数字"9"是一个可以代表任何数字的占位字符):

...

' 建立一个电话号码的编辑掩码。
_flex.Cols(1).EditMask = "(999) 999-9999"

  • C#

// 建立一个电话号码的编辑掩码。

Wiki Markup
_flex.Cols\[1\].EditMask = "(999) 999-9999";


当你将"编辑掩码"属性设置为一个非空的字符串,会导致它必须使用内
置的屏蔽编辑,即便该列包含日期/时间值(通常,一个"日期时间提取器"控件可以用于编辑这些列)。如果你有只含时间(没有日期)的"日期时间" 列,这使用起来将格外方便。在这些情况下,你可以设置以下属性来使用一个屏蔽编辑器,而不是一个"日期时间提取器"控件:

...

flex.Cols(1).DataType = GetType(DateTime)
_flex.Cols(1).Format = "hh:mm tt"
_flex.Cols(1).EditMask = "99:99 LL"

  • C#


Wiki Markup
flex.Cols\[1\].DataType = typeof(DateTime);



Wiki Markup
_flex.Cols\[1\].Format = "hh:mm tt";




Wiki Markup
_flex.Cols\[1\].EditMask = "99:99 LL";



你也可以在设计时通过使用"输入掩码"对话框来设置"编辑掩码"属性。
要访问输入掩码对话框可通过以下两种途经,"列任务"菜单或
C1FlexGrid 列编辑器

...

  • Visual Basic

    Private Sub _flex_ValidateEdit(ByVal sender As Object, ByVal e As C1.Win.C1FlexGrid.ValidateEditEventArgs) Handles _flex.ValidateEdit
    ' 验证金额。
    If _flex.Cols(e.Col).DataType Is GetType(Decimal) Then Try
    Dim dec As Decimal = Decimal.Parse(_flex.Editor.Text())
    If (dec < 1000) Or (dec > 10000) Then
    MessageBox.Show("Value must be between 1,000 and 10,000") e.Cancel = True
    End If
    Catch
    MessageBox.Show("Value not recognized as a Currency") e.Cancel = True
    End Try
    End If
    End Sub


  • C#

    private void _flex_ValidateEdit( object sender, ValidateEditEventArgs e)
    {
    // 验证金额。

    Wiki Markup
    if (_flex.Cols\[e.Col\].DataType == typeof(Decimal))


    { try
    {
    Decimal dec = Decimal.Parse(_flex.Editor.Text); if ( dec < 1000 || dec > 10000 ) {
    MessageBox.Show("Value must be between 1,000 and 10,000"); e.Cancel = true;
    }
    }
    catch
    {
    MessageBox.Show("Value not recognized as a Currency"); e.Cancel = true;
    }
    }
    }



    自定义编辑器

    内置的编辑器可以具备很大的灵活性和能力,但在某些情况下,你可能要使用外部控件作为专门的编辑器。例如,你可能想使用提供了一个下拉计算器的 C1NumericInput 控件来输入数字,或使用一个编辑器来从多列的列表中进行选择,或你可以用自己写的一个专门的控件来编辑你的业务对象。
    从基本的"控件"类型派生出的任何控件都可以作为一个基本的表格编辑
    器使用。实现了 IC1EmbeddedEditor 接口(在 C1.Common.dll 的定义)的控件可
    以用表格提供更好的整合和更先进的功能。有关 IC1EmbeddedEditor 接口的更多详细信息,请参阅"编辑属性"。
    要将一个控件作为自定义编辑器来使用,所有你必须要做的就是使用其
    "编辑"属性将控件的一个实例与一个表格列或一个样式关联到一起。你可以在设计器(使用列编辑器)或在代码中实现这步操作。在此之后,表格将自动使用该控件。
    要在设计时定义自定义编辑器,先要将编辑器控件的一个实例添加到窗
    体,然后从 C1FlexGrid 任务菜单上选择设计器来打开 C1FlexGrid 列编辑器。选择应使用自定义编辑器的列,并将其编辑器的属性设置为新的编辑器控件的名称。
    例如,要将 NumericUpDown 控件作为一个表格编辑器使用,请按照下列步骤操作:

...

private void Form1_Load(object sender, System.EventArgs e)
{
// 创建自定义编辑器。
NumericUpDown editor = new NumericUpDown();
editor.BorderStyle = BorderStyle.None;
// 将自定义编辑器分配到表格。

Wiki Markup
_flex.Cols\[1\].Editor = editor;


}
创建自定义编辑器从 Control 基类派生出的任何控件都可以用来作为一个表格编辑器使用。这
是完全有可能的,因为在访问诸如"文本"和"界限"之类的属性,或诸如 "请假"和"文本变更"之类的事件时,表格对基类控件有足够的了解。在很多情况下,这种程度的支持就足够了。然而,在某些情况下,你可能想使用一些不那么密切地遵守基类的控件。例如,"日期时间提取器"控件有一个""属性,它应该用来检索编辑过的值,而不是文本的值。在这些情况下,你可以在 IC1EmbeddedEditor 接口上实现一个或多个方法来覆盖默认的行为。例如,在 C1Input 库中所有控件都支持
IC1EmbeddedEditor,因此,它与 C1FlexGrid(还有 C1TrueDBGrid)整合密切。
IC1EmbeddedEditor 接口相当简单,并且由于表格是使用后期绑定与之相结合的,你甚至不需要实现其所有成员。只需要落实那个对你的编辑器控件有意义的即可。
接口确实提供了足够的灵活性来使几乎所有的控件都能作为一个表格编辑
器使用。你甚至可以使用 UITypeEditor 这些类型来作为表格编辑器。要做到这一点,你需要一个包装类:

...

  • Visual Basic

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Load Dim i%
    ' 初始化该控件。
    _flex.Styles.Normal.WordWrap = True
    _flex.Cols.Count = 9
    _flex.Rows.Fixed = 2
    _flex.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.FixedOnly
    ' 创建行标题。
    _flex.Rows(0).AllowMerging = True
    ' 合并含有相同内容的四个单元格。
    Dim rng As C1.Win.C1FlexGrid.CellRange = _flex.GetCellRange(0, 1, 0, 4) rng.Data = "North"
    ' 合并含有相同内容的四个单元格。
    rng = _flex.GetCellRange(0, 5, 0, 8) rng.Data = "South"
    For i = 1 To 4
    _flex(1, i) = "Qtr " & i
    _flex(1, i + 4) = "Qtr " & i Next
    ' 创建列标题。
    _flex.Cols(0).AllowMerging = True
    ' 合并含有相同的内容的两个单元格。
    rng = _flex.GetCellRange(0, 0, 1, 0)
    rng.Data = "Sales by Product"
    ' 对齐单元格和自动调整单元格大小。
    _flex.Styles.Fixed.TextAlign =
    C1.Win.C1FlexGrid.TextAlignEnum.CenterCenter
    _flex.AutoSizeCols(1, _flex.Cols.Count - 1, 10)


  • C#

    private void Form1_Load(System.object sender, System.EventArgs e)
    {
    int i;
    // 初始化该控件。
    _flex.Styles.Normal.WordWrap = true;
    _flex.Cols.Count = 9;
    _flex.Rows.Fixed = 2;
    _flex.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.FixedOnly;
    // 创建行标题。

    Wiki Markup
    _flex.Rows\[0\].AllowMerging = true;


    // 合并含有相同内容的四个单元格。
    C1.Win.C1FlexGrid.CellRange rng = _flex.GetCellRange(0, 1, 0, 4); rng.Data = "North";
    // 合并含有相同内容的四个单元格。
    rng = _flex.GetCellRange(0, 5, 0, 8); rng.Data = "South";
    for ( i = 1 ; i <= 4; i++)
    {


    Wiki Markup
    _flex\[1, i\] = "Qtr " + i;




    Wiki Markup
    _flex\[1, i + 4\] = "Qtr " + i;



    }
    // 创建列标题。


    Wiki Markup
    _flex.Cols\[0\].AllowMerging = true;



    // 合并含有相同的内容的两个单元格。
    rng = _flex.GetCellRange(0, 0, 1, 0);
    rng.Data = "Sales by Product";
    // 对齐单元格和自动调整单元格大小。
    _flex.Styles.Fixed.TextAlign =
    C1.Win.C1FlexGrid.TextAlignEnum.CenterCenter;
    _flex.AutoSizeCols(1, _flex.Cols.Count - 1, 10);
    }


    以下是结果:

    合并后的数据视图

    当表格被绑定到一个数据源时,单元格合并会以同样的方式进行。下面的代码显示了一个在设计时表格绑定到数据源的例子。有关绑定到一个数据源的更多详细信息,请参阅"绑定到一个数据源"(第 95 页)。
  • Visual Basic

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
    System.EventArgs) Handles MyBase.Load Dim i%
    ' 设置单元格合并。
    _flex.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.RestrictCols
    For i = _flex.Cols.Fixed To _flex.Cols.Count - 1
    _flex.Cols(信息).AllowMerging = True
    Next
    End Sub


  • C#

...

' 设置分类汇总的样式。
Dim cs As C1.Win.C1FlexGrid.CellStyle cs = _flex.Styles(C1.Win.C1FlexGrid.CellStyleEnum.GrandTotal) cs.BackColor = Color.Black cs.ForeColor = Color.White cs.Font = New Font(Font, FontStyle.Bold) cs = _flex.Styles(C1.Win.C1FlexGrid.CellStyleEnum.Subtotal0) cs.BackColor = Color.DarkRed cs.ForeColor = Color.White cs.Font = New Font(Font, FontStyle.Bold) cs = _flex.Styles(C1.Win.C1FlexGrid.CellStyleEnum.Subtotal1) cs.BackColor = Color.DarkBlue cs.ForeColor = Color.White

  • C#

// 设置分类汇总的样式。

Wiki Markup
CellStyle cs;  cs = _flex.Styles\[CellStyleEnum.GrandTotal\];  cs.BackColor = Color.Black;  cs.ForeColor = Color.White;  cs.Font = new Font(Font, FontStyle.Bold);  cs = _flex.Styles\[CellStyleEnum.Subtotal0\];  cs.BackColor = Color.DarkRed;  cs.ForeColor = Color.White;  cs.Font = new Font(Font, FontStyle.Bold);  cs = _flex.Styles\[CellStyleEnum.Subtotal1\];  cs.BackColor = Color.DarkBlue;  cs.ForeColor = Color.White;


执行此代码后,表格看起来是这样的:

总计行中包含的所有产品,地区和销售人员的销售总额。它是使用
groupOn 参数-1 在调用 C1FlexGrid.Subtotal 方法时被创建的。其他分类汇总显示产品和地区的销售总额。他们是用 Groupon 的参数值 0 和 1 创造的。
除了总量之外,你也可以计算其他分类汇总(例如,平均值或百分比),并计算每一行的几个汇总(例如,毛销售额及净销售额)。
分类汇总的方法创建的小计行不同于其他普通行,主要体现在三个方面:

...

private void AddDirectory(string dir, int level)
{
// 添加该目录。
string thisDir = Path.GetFileName(dir); if (thisDir.Length == 0) { thisDir = dir; }
_flex.AddItem(thisDir);
// 使这个新行成为一个节点。

Wiki Markup
Row row = _flex.Rows\[_flex.Rows.Count - 1\];  row.IsNode = true;


// 设置该节点的层级。
Node nd = row.Node;
nd.Level = level;
// 在此目录中添加文件。
int cnt = 0; Row r; foreach (string file in Directory.GetFiles(dir))
{
_flex.AddItem(Path.GetFileName(file).ToLower());
// 将没有子行的行标记为节点。


Wiki Markup
r = _flex.Rows\[_flex.Rows.Count - 1\];  r.IsNode = true;



r.Node.Level = level + 1; cnt = cnt + 1; if (cnt > 10) break;
}
// 添加子目录(到 4 级)。
if (level <= 4)
{
cnt = 0; foreach (string subdir in Directory.GetDirectories(dir))
{
AddDirectory(subdir, level + 1); cnt = cnt + 1; if (cnt > 10) break;
}
}
}


...

的。如果你的数据源在设计时是可用的,你可以使用 Visual Studio 属性窗口来设置表格的"数据源"属性,并且无需编写任何代码就可以将表格绑定到数据。
如果数据源在设计时是不可用的,你可以在代码中设置表格的"数据源" 属性。数据绑定代码看起来通常是这样的:
代码使用一个 OleDbDataAdapter 来用数据填充一个数据表,然后,将数据表分配给表格的"数据源"属性。
运行此代码后,你会看到在第一张图片中显示了一个"普通的表格"。要使这个普通的表格变成第二张图片中显示的那种大纲型表格,我们需要插入节点行来整理这个大纲。
创建节点行
节点行几乎都是同样的普通行,但以下情况除外:
public Form1()
{
InitializeComponent();
// 获取数据
var fields = @"
Country,
City,
SalesPerson,
Quantity, ExtendedPrice"; var sql = string.Format("SELECT {0} FROM Invoices ORDER BY {0}", fields);
var da = new OleDbDataAdapter(sql, GetConnectionString()); da.Fill(_dt); // 将表格绑定到数据
this._flex.DataSource = _dt;
// 为"总价"列设置格式

Wiki Markup
_flex.Cols\["ExtendedPrice"\].Format = "n2";


}


  • 节点行不是数据绑定。当表格被绑定到一个数据源时,每个普通的行会对应数据源中的一个项目。而节点行则不然。相反,它们的存在是为了给包含类似数据的普通行分组。
  • 节点行可以折叠或展开。当一个节点行折叠起来时,它的所有数据和子节点都隐藏起来了。如果大纲树型图可见,用户可以用鼠标或键盘来折叠和展开节点。如果大纲树型图不可见,则只能用代码来扩展或折叠节点。你可以使用"是节点"属性来确定一个行是否是节点行:节点行可以用以下三种方法来创建:
  1. 使用 Rows.InsertNode 方法。这将在指定的索引中插入一个新的节点行。一旦该节点行被创建成功,你可以像使用任何其他行一样使用它(设置每列的数据、应用样式等)。
  2. 使用 C1FlexGrid.Subtotal 方法。这种方法会在表格中数据发生变化的地方用可选的分类汇总来扫描整个表格并自动插入节点行。这是插入汇总和构建大纲的"高层次"方式。它只需要非常少的代码,但对表格中的数据是如何排列的和大纲看起来应该像什么样子做了一些相关的假设。


Wiki Markup
var row = _flex.Rows\[rowIndex\];  if (row.IsNode)


{
// 该行是一个节点 var node = row.Node;
DoSomethingWithTheNode(node);
}
else
{
// 该行不是一个节点
}
3. 如果表格是未绑定的,那么你可以通过将 "是节点"属性设置为"真" 来将一些普通行变成节点行。请注意,这仅限于当表格处于未绑定的状态下。试图将一个普通的数据绑定行变成一个节点,可能会造成表格抛出一个异常。
以下的代码演示了你应该如何来执行一个"分组依据"程序,插入节点行并对一个给定列的近似值进行分组。

...

// 在给定列上将插入的同一个给定级别的节点分组
void GroupBy(string columnName, int level)
{
object current = null; for (int r = _flex.Rows.Fixed; r < _flex.Rows.Count; r++)
{

Wiki Markup
if (!_flex.Rows\[r\].IsNode)


{


Wiki Markup
var value = _flex\[r, columnName\];  if (!object.Equals(value, current))



{
// 值的变化:插入节点
_flex.Rows.InsertNode(r, level);
// 在第一个滚动列显示分组的名称


Wiki Markup
_flex\[r, _flex.Cols.Fixed\] = value;



// 更新当前值
current = value;
}
}
}
}


...

// unbind and re-bind grid in order to reset everything void ResetBinding()
{
// 解除绑定表格
_flex.DataSource = null;
// 重置任何自定义排序
_dt.DefaultView.Sort = string.Empty;
// 重新绑定表格
_flex.DataSource = _dt;
// 设置总价列的格式

Wiki Markup
_flex.Cols\["ExtendedPrice"\].Format = "n2";


// 自动调整列宽以适配其内容
flex.AutoSizeCols();
}


...

// 在一个给定层级的每个节点添加分类汇总
void AddSubtotals(int level, string colName)
{
// 获取我们将要进行汇总的列
int colIndex = _flex.Cols.IndexOf(colName);
// 为找到合适层级的节点对行进行扫描
for (int r = _flex.Rows.Fixed; r < _flex.Rows.Count; r++)
{

Wiki Markup
if (_flex.Rows\[r\].IsNode)


{


Wiki Markup
var node = _flex.Rows\[r\].Node;  if (node.Level == level)



{
// 找到一个节点,计算总价的总和
var range = node.GetCellRange(); var sum = _flex.Aggregate(AggregateEnum.Sum, range.r1, colIndex, range.r2, colIndex, AggregateFlags.ExcludeNodes);
// 在表格上显示总和
// (将自动使用列格式)


Wiki Markup
_flex\[r, colIndex\] = sum;



}
}
}
}



Wiki Markup
"{*}添加分类汇总{*}"方法可以扫描所有表格中的行来寻找节点行。当一个理想层级的节点行被发现时, 该方法可以使用"获取单元格区域"的方法来检索节点的子行。然后它使用 C1FlexGrid.Aggregate 方法来计算整个范围内目标列中值的总和。{*}聚合{*}的调用包括一个可以避免重复计算的现有节点的"{*}排除节点{*}" 的标志。一旦小计已经被计算,它就会与通常的_{*}flex\[行,彩色\]{*}索引一起被分配到节点行的单元格。 
请注意,这并不会以任何方式影响到数据源,因为节点行并没有绑定到数据。还要注意,该方法可以被用来将多个汇总添加到每个节点行。在这个例子中,我们将增加数量和总价列的汇总。除了总金额,你还可以添加其他的集合值,比如平均值,最高值,最低值等等。 
现在我们可以用这种方法来创建一个包括节点行、大纲树型图以及分类汇
总的完整的大纲: 
<span style="color: #1f497d">void _btnTreeCountryCity_Click(object sender, EventArgs e)</span>  
<span style="color: #1f497d">{</span>  
<span style="color: #1f497d">using (new DeferRefresh(_flex))</span>  
<span style="color: #1f497d">{</span>  
<span style="color: #1f497d">// 恢复原来的排序(按照国家、城市、销售人员)</span> 
<span style="color: #1f497d">ResetBinding();</span>  
<span style="color: #1f497d">// 按照国家、城市分组</span> 
<span style="color: #1f497d">GroupBy("Country", 0); // 按 country (level 0) 分组</span> 
<span style="color: #1f497d">GroupBy("City", 1);  // 按 city (level 1) 分组</span> 
<span style="color: #1f497d">// 添加每个国家、城市的总数</span> 
<span style="color: #1f497d">AddSubtotals(0, "ExtendedPrice"); //extended price per  country (level 0)</span>  
<span style="color: #1f497d">AddSubtotals(0, "Quantity");  // quantity per country</span>  
<span style="color: #1f497d">(level  0)</span>  
<span style="color: #1f497d">AddSubtotals(1, "ExtendedPrice");  // extended price per city</span>  
<span style="color: #1f497d">(level  1)</span>  
<span style="color: #1f497d">AddSubtotals(1, "Quantity");  // quantity per city (level 1)</span>  
<span style="color: #1f497d">// 显示大纲树型图</span> 
<span style="color: #1f497d">_flex.Tree.Column = 0;</span>  
<span style="color: #1f497d">_flex.AutoSizeCol(_flex.Tree.Column);</span>  
<span style="color: #1f497d">_flex.Tree.Show(1);</span>  
<span style="color: #1f497d">}</span>  
<span style="color: #1f497d">}</span>  
如果你现在运行该项目,你会看到一个由节点行组成的树型图,其中显示
了每个国家和城市的销售总数量和金额。虽然这非常好,但还是有一个小问题。如果你展开任何节点行,你会看到大量的重复值。一个给定的城市节点下的所有行都有相同的国家和城市: 
!worddav93d6bd43a4f75b9b63be7814494af425.png|height=305,width=529! 这是正确的,但它同时也是一种 屏幕实际使用面积的浪费。消除这些重复的值是很容易的;所有你所需要做的只是将正在被分组的列的{*}宽度{*}设置为零。
然而,当你这样做时,你应该记得将表格的"允许合并"属性设置为"节
点",以便使分配给节点行的文本可以溢出到可见列。(另一种选择是将节点的文本指定到第一个可见列,但合并通常是一个更好的解决方案,因为它可以让你在节点行使用更长的文本)。 
下面是修改后的代码和最终结果: 

...

void _btnTreeCountryCity_Click(object sender, EventArgs e)
{
using (new DeferRefresh(_flex))
{
// 恢复原来的排序(按照国家、城市、销售人员)
ResetBinding();
// 按照国家、城市来分组
GroupBy("Country", 0); // group by country (level 0)
GroupBy("City", 1); // group by city (level 1)
// 隐藏我们分过组的那些列
// (他们只有在树型图节点上已经出现过的那些重复的值)
// (但不要使它们不可见,这可能会隐藏节点的文本)

Wiki Markup
_flex.Cols\["Country"\].Width = 0;  _flex.Cols\["City"\].Width = 0;


// 允许节点的内容溢出到下一个单元格
_flex.AllowMerging = AllowMergingEnum.Nodes;
// 添加每个国家和城市的总数
AddTotals(0, "ExtendedPrice"); // extended price per country
(level 0)
AddTotals(0, "Quantity"); // quantity per country (level
0)
AddTotals(1, "ExtendedPrice"); // extended price per city
(level 1)
AddTotals(1, "Quantity"); // quantity per city (level
1)
// 显示大纲树型图
_flex.Tree.Column = 0;
_flex.AutoSizeCol(_flex.Tree.Column);
_flex.Tree.Show(1);
}
}


...

在前面我们曾经提到,你也可以使用 C1FlexGrid 的 C1FlexGrid.分类汇总方法来创建树型图。除了可以在一个单一的步骤里同时做两件事以外,这种分类汇总的方法也可以像以上所描述的"分组依据"和"添加分类汇总"一样来执行相同的任务,因此它比其他的更高效一些。
下面的代码显示了你应该如何使用分类汇总的方法来完成我们之前做过的
同样的事情,只是要比之前更快一点而且不需要使用任何辅助方法:
void _btnTreeCountryCity_Click(object sender, EventArgs e)
{
using (new DeferRefresh(_flex))
{
// 恢复原来的排序(按照国家、城市、销售人员)
ResetBinding();
// group and total by country and city
_flex.Subtotal(AggregateEnum.Sum, 0, "Country",
"ExtendedPrice");
_flex.Subtotal(AggregateEnum.Sum, 0, "Country", "Quantity");
_flex.Subtotal(AggregateEnum.Sum, 1, "City", "ExtendedPrice");
_flex.Subtotal(AggregateEnum.Sum, 1, "City", "Quantity");
// 隐藏我们分过组的那些列
// (他们只有在树型图节点上已经出现过的那些重复的值)
// (但不要使它们不可见,这可能会隐藏节点的文本)

Wiki Markup
_flex.Cols\["Country"\].Width = 0;



Wiki Markup
_flex.Cols\["City"\].Width = 0;



_flex.AllowMerging = AllowMergingEnum.Nodes;
// 显示大纲树型图
_flex.Tree.Column = 0;
_flex.AutoSizeCol(_flex.Tree.Column);
_flex.Tree.Show(1);
}
}
分类汇总的方法非常方便和灵活。它包含多个重载,能够使你明确应该对
哪些列进行分组并按照索引或名称来合计总数,是否包括它插入节点行的标题,以及如何进行分组等等。下面的摘要介绍了可用的重载:

...

"节点"类提供了许多可以用来创建和管理大纲树型图的方法和属性。这些方法和属性中的许多都是基于标准的 TreeView 对象模型,因此他们应该熟悉大多数的开发者。
为了获得一个"节点"对象,你可以:
使用 Rows.InsertNode 方法的返回值:
Var node = _flex.Rows.InsertNode(index, level);
或者,你可以用行的节点属性来在现有的一行检索节点:

Wiki Markup
Var node = _flex.Rows\[index\].IsNode



Wiki Markup
_flex.Rows\[index\].Node   null;



无论哪种方式,一旦你有了一个"节点"对象,你就可以使用以下属性和方法来操作它:

...

  • Visual Basic

    Private Sub _btnData_Click(ByVal sender As Object, ByVal e As
    System.EventArgs) Handles _btnData.Click
    ' 准备好 DataReader。
    Dim strConn As String = "data source=MYMACHINE;initial catalog=Northwind;"
    Dim myConn As New SqlClient.SqlConnection(strConn)
    Dim myCMD As New SqlClient.SqlCommand("SELECT * FROM Employees", myConn) myConn.Open()
    Dim myReader As SqlClient.SqlDataReader = myCMD.ExecuteReader()
    ' 从 DB 模式来建立表格结构。
    Dim dt As DataTable = myReader.GetSchemaTable()
    _flex.Cols.Count = 1
    Dim dr As DataRow
    For Each dr In dt.Rows
    Dim c As C1.Win.C1FlexGrid.Column = _flex.Cols.Add() c.Caption =(c.Name <= CStr(dr("ColumnName")))
    c.DataType = CType(dr("DataType"), Type) Next dr
    ' 填充表格。
    _flex.Rows.Count = 1
    Dim row As Integer = 1
    Dim cols As Integer = dt.Columns.Count
    Dim v As Object() = CType(Array.CreateInstance(GetType(Object), cols), Object())
    While myReader.Read() myReader.GetValues(v)
    _flex.AddItem(v, row + 1, 1) End While
    ' 清理。
    _flex.AutoSizeCols() myReader.Close() myConn.Close()


  • C#

    private void _btnData_Click(object sender, System.EventArgs e)
    {
    // 准备好 DataReader。
    string strConn = "data source=MYMACHINE;initial catalog=Northwind;";
    System.Data.SqlClient.SqlConnection myConn = new
    System.Data.SqlClient.SqlConnection(strConn);
    System.Data.SqlClient.SqlCommand myCMD = new
    System.Data.SqlClient.SqlCommand("SELECT * FROM Employees", myConn); myConn.Open();
    System.Data.SqlClient.SqlDataReader myReader = myCMD.ExecuteReader();
    // DB 模式来建立表格结构。
    DataTable dt = myReader.GetSchemaTable();
    _flex.Cols.Count = 1; foreach (DataRow dr in dt.Rows)
    {
    Column c = _flex.Cols.Add();

    Wiki Markup
    c.Caption = c.Name = (string)dr\["ColumnName"\];



    Wiki Markup
    c.DataType = (Type)dr\["DataType"\];



    // 填充表格。


    Wiki Markup
    _flex.Rows.Count = 1;  int row = 1;  int cols = dt.Columns.Count;  object\[\] v = (object\[\])Array.CreateInstance(typeof(object), cols);  while (myReader.Read())



    {
    myReader.GetValues(v);
    _flex.AddItem(v, row++, 1);
    }
    // 清理。
    _flex.AutoSizeCols(); myReader.Close(); myConn.Close();
    }



     打印表格

    使用"打印表格"方法来打印表格的内容。该方法具有可以让你选择缩放模式,是否显示打印/预览对话框,设置页眉和页脚,等等的参数。
    "打印参数"属性可以公开额外的打印性能,如字体,使用页眉和页脚,而一个.NET Framework "打印文档"对象可以用来选择打印机,纸张大小和方向,页边距等。
    下面的代码使用了"打印参数"属性来设置页面方向、页边距、页眉和页脚的字体。然后它调用"打印表格"方法来显示打印预览对话框窗口:
  • Visual Basic

    ' 获取表格的"打印文档"对象。
    Dim pd As Printing.PrintDocument pd = _flex.PrintParameters.PrintDocument()
    ' 设置页面(横向打印,左边页边距 1.5")。
    With pd.DefaultPageSettings
    .Landscape = True
    .Margins.Left = 150 End With
    ' 设置页眉和页脚的字体。
    _flex.PrintParameters.HeaderFont = New Font("Arial Black", 14,
    FontStyle.Bold)
    _flex.PrintParameters.FooterFont = New Font("Arial Narrow", 8,
    FontStyle.Italic)
    ' 预览表格。
    _flex.PrintGrid("C1FlexGrid",
    C1.Win.C1FlexGrid.PrintGridFlags.FitToPageWidth +
    C1.Win.C1FlexGrid.PrintGridFlags.ShowPreviewDialog, "C1FlexGrid" + Chr(9)
    +


  • C#

...

正如我们前面提到的这个文件,设置表格的"允许过滤"属性为"",这足以让所有的列进行列过滤。然而,在许多情况下,你可能需要更精细的过滤控制。这可以通过修改个别列的"允许过滤"和"过滤"属性来实现。例如,下面的代码使能够启用过滤,但对过滤字符串类型的列进行了限制:
// 绑定和配置表格
flex.DataSource = dtProducts;

Wiki Markup
_flex.Cols\["UnitPrice"\].Format = "#,###.00";


// 启用过滤
_flex.AllowFiltering = true;
// 限制过滤 "字符串"类型的列
foreach (Column c in _flex.Cols)
{
c.AllowFiltering = c.DataType == typeof(string)
? AllowFiltering.Default
: AllowFiltering.None;
}
你可以通过创建过滤器并将他们分配到列,或通过检索现有的过滤器并修改其属性,来进一步自定义过滤过程。例如,下面的代码创建了一个"条件过滤器",配置它来选择所有以字母"C"开头的项目,然后分配这个新的过滤器给"产品名称"一列:

...

// 创建一个新的"条件过滤器"
var filter = new ConditionFilter(); // 配置过滤器来选择以"C"开始的项目
filter.Condition1.Operator = ConditionOperator.BeginsWith; filter.Condition1.Parameter = "C";
// 分配新的过滤器到"产品名称"列

Wiki Markup
_flexCustom.Cols\["ProductName"\].Filter = filter;




 程序化地应用过滤器

当用户编辑他们或当他们适用于一列时,过滤器是适用的。当数据发生变化时,它们不会自动应用。
要将过滤器应用到从表格加载的当前的数据,请调用表格的"应用过滤器"方法。
例如,当用户编辑表格上的数据时,下面的代码启用了一个"应用过滤器"按钮。点击这个"应用过滤器"按钮即可应用该过滤器,并可以直到下一次的变化前禁用该按钮。
public Form1()
{
InitializeComponent();
// 获取一些数据
var da = new OleDbDataAdapter("select * from products", GetConnectionString()); var dtProducts = new DataTable(); da.Fill(dtProducts);
// 将表格绑定到数据_
flex.DataSource = dtProducts;
// 启用过滤
_flex.AllowFiltering = true;
// 监测变化以便启用"应用过滤器"按钮
_flex.AfterEdit += _flex_AfterEdit;
}
上面的代码可以将一个表格绑定到数据源,可以通过将"允许过滤"属性
设置为"真"来启用过滤器,并可以连接一个事件处理程序到"编辑后"事件。事件处理程序的执行情况如下:

...

// 在应用过滤器之前暂停绘制
void _flex_BeforeFilter(object sender, CancelEventArgs e)
{
_flexStyles.BeginUpdate();
}
// 在应用过滤器之后应用样式
void _flexStyles_AfterFilter(object sender, EventArgs e)
{
// 获取用于显示筛选出的行的样式

Wiki Markup
var cs = _flex.Styles\["filteredOut"\];


// 将样式应用于所有行
for (int r = _flexStyles.Rows.Fixed; r < _flexStyles.Rows.Count; r++)
{


Wiki Markup
var row = _flexStyles.Rows\[r\];  if (row.Visible)



{
// normal row, reset style row.Style = null;
}
else
{
// 过滤行,使其可见并应用样式
row.Visible = true; row.Style = cs;
}
}
// 恢复更新_
flexStyles.EndUpdate();
}


...

// 在计时器滴答计时时应用过滤器
void t_Tick(object sender, EventArgs e)
{
// done for now...
_timer.Stop();
// 配置过滤器
var filter = new C1.Win.C1FlexGrid.ConditionFilter(); filter.Condition1.Operator =
C1.Win.C1FlexGrid.ConditionOperator.Contains;
filter.Condition1.Parameter = _txtSearch.Text;
// 应用过滤器
_flex.BeginUpdate(); for (int r = _flex.Rows.Fixed; r < _flex.Rows.Count; r++)
{
bool visible = false; for (int c = _flex.Cols.Fixed; c < _flex.Cols.Count; c++)
{

Wiki Markup
if (filter.Apply(_flex\[r, c\]))


{
visible = true; break;
}
}


Wiki Markup
_flex.Rows\[r\].Visible = visible;



}
_flex.EndUpdate();
}


 C1FlexGrid 的属性组

...