Component One C# c1FlexGrid 帮助文档
Value-Mapped Lists(值映射列表)
功能描述:上述财产的ComboList确保单元格的值是从名单中挑选。由用户选择的值转换成列的适当类型和存储在网格,完全一样,如果用户已输入的值。
在许多情况下,细胞能够承担来自明确列出的值,但是你想显示一个用户的实际价值的版本。例如,如果一个列包含的产品代码,您可能要存储的代码,但显示的产品名称来代替。
这是通过的DataMap财产。此属性包含一个引用到的IDictionary对象之间建立什么是存储在网格中,什么是可见的用户(IDictionary接口是System.Collections命名空间中定义,并得到其他Hashtable类中实现)映射。
例如,下面的代码创建了一个数据映射,它包含颜色值,他们的名字。这些颜色都存储在网格中,他们的名字所显示的用户:
功能示例:
1 System.Collections.Hashtable dtMap = new System.Collections.Hashtable(); 2 3 dtMap.Add(Color.Red, "Apple"); 4 5 dtMap.Add(Color.Green, "Forest"); 6 7 dtMap.Add(Color.Blue, "Sky"); 8 9 dtMap.Add(Color.Black, "Coal"); 10 11 dtMap.Add(Color.White, "Snow"); 12 13 _flex.Cols[1].DataType = typeof(Color); 14 15 _flex.Cols[1].DataMap = dtMap;
实现IDictionary的任何类可以作为一个DataMap使用。例如,哈希表,ListDictionary的,和SortedList都提供了有效的数据地图。所不同的是,当他们在编辑栏使用时,在下拉列表中项目的顺序将取决于类。
各种各样的SortedList类的重点项目,Hashtable的使用任意命令,ListDictionary的保持在哪些项目被添加到列表的顺序。正因为如此,ListDictionary的通常是为DataMaps的最佳选择。
请注意,在数据映射的键必须为同一类型的细胞被编辑。例如,如果一个列包含短整数(Int16的),那么任何数据列关联应该有短整数键地图。作为**不会正常工作整数(Int32的)。
下面的例子显示的区别:
1 private void Form1_Load(object sender, System.EventArgs e); 2 3 { 4 5 // Sorts by key. 6 7 System.Collections.SortedList sl = new System.Collections.SortedList(); 8 9 sl.Add("0", "Zero"); 10 11 sl.Add("1", "One"); 12 13 sl.Add("2", "Two"); 14 15 sl.Add("3", "Three"); 16 17 18 19 // Keeps Add order. 20 21 System.Collections.Specialized.ListDictionary ld = new System.Collections.Specialized.ListDictionary(); 22 23 ld.Add(0, "Zero"); 24 25 ld.Add(1, "One"); 26 27 ld.Add(2, "Two"); 28 29 ld.Add(3, "Three"); 30 31 32 33 // Arbitrary order. 34 35 System.Collections.Hashtable ht = new System.Collections.Hashtable(); 36 37 ht.Add(0, "Zero"); 38 39 ht.Add(1, "One"); 40 41 ht.Add(2, "Two"); 42 43 ht.Add(3, "Three"); 44 45 46 47 _flex.Cols[1].DataMap = sl; 48 49 _flex.Cols[1].Caption = "SortedList"; 50 51 _flex.Cols[2].DataMap = ld; 52 53 _flex.Cols[2].Caption = "ListDictionary"; 54 55 _flex.Cols[3].DataMap = ht; 56 57 _flex.Cols[3].Caption = "HashTable"; 58 59 }
Cell Buttons (细胞按钮)
功能描述:某些类型的细胞,可能需要较复杂的编辑文本框或下拉列表等。例如,如果一个列包含文件名称或一种颜色,它应该是一个对话框编辑。
在这种情况下,你应该设置ComboList属性省略号(“...”)。该控件将显示一个按钮,旁边的单元格,将触发CellButtonClick事件当用户点击就可以了。您可以捕获的事件,显示该对话框,并更新用户的选择单元格的内容。
如果您添加一个省略号前管道字符,那么用户将被允许进入细胞编辑输入单元格内容。
默认情况下,细胞按钮显示省略号。您可以指定图片的单元格按钮使用CellButtonImage财产。
下面演示了如何使用手机的按钮显示选择列中的某个颜色的颜色选择器对话框的例子。
功能示例:
1 // Set up color column. 2 3 Column c = _flex.Cols[1]; 4 5 c.DataType = typeof(Color); 6 7 8 9 // Show cell button. 10 11 c.ComboList = "...";
此代码设置列,以便用户可以点击一个按钮,然后从对话框中的颜色。下一步是处理的代码单元格按钮上点击:
1 private void _flex_CellButtonClick( object sender, RowColEventArgs e) 2 3 { 4 5 // Create color picker dialog. 6 7 ColorDialog clrDlg = new ColorDialog(); 8 9 10 11 // Initialize the dialog. 12 13 if (_flex[e.Row, e.Col] == typeof(Color)) 14 15 { 16 17 clrDlg.Color = (Color)_flex[e.Row, e.Col]; 18 19 } 20 21 22 23 // Get new color from dialog and assign it to the cell. 24 25 if (clrDlg.ShowDialog() == DialogResult.OK) 26 27 { 28 29 _flex[e.Row, e.Col] = clrDlg.Color; 30 31 } 32 33 }
Masks(面具)
该C1FlexGrid控件还支持蒙面编辑。使用这种类型的编辑输入掩码提供一个模板,并自动验证用户类型作为输入。面具是指定的EditMask属性,可以用正则文本字段和下拉式组合领域。
面膜字符串有两种类型的字符:字面字符,成为输入部分和模板字符,这为属于特定类别中的字符为占位符(例如,数字或字母)。例如,下面的代码指定一个“(999)999-9999”,以第一列,它包含电话号码的编辑掩码(数字“9”是一个占位符,对于任何数字的缩写):
代码示例:
1 // Set up a phone number edit mask. 2 3 _flex.Cols[1].EditMask = "(999) 999-9999";
EditMask属性设置为一个非空字符串会导致它使用内置的蒙面编辑器,即使该列包含日期/时间值(通常,一个DateTimePicker控件用于编辑这些列)。这是特别方便,如果您有DateTime列持有时间(无日期)。在这种情况下,可以设置以下属性,以使用,而不是在DateTimePicker控制蒙面编辑:
1 _flex.Cols[1].DataType = typeof(DateTime); 2 3 _flex.Cols[1].Format = "hh:mm tt"; 4 5 _flex.Cols[1].EditMask = "99:99 LL";
对话框中输入掩码可以通过菜单或任务列通过C1FlexGrid列编辑器。
在任务菜单•列,单击编辑掩码框中的省略号按钮。
•在C1FlexGrid栏编辑器,找到在左窗格中的EditMask属性,单击省略号按钮旁边。
注意:在输入掩码列的特定对话框,只会改变所选列EditMask属性。
有关用来建立遮罩字串语法的详细信息,请参阅参考部分EditMask控制的财产。
如果在同一列中不同的细胞需要不同的面具,捕获BeforeEdit事件,并设置EditMask属性为当前单元格适当的值。
Validation(验证)
功能描述:在许多情况下,编辑口罩本身是不够的,以确保用户输入的数据是有效的。例如,一个面具不会让你指定一个可能值的范围,或验证当前单元格在另一个单元格的内容为基础。
在这种情况下,捕获ValidateEdit事件,看看在Editor.Text属性中包含的值是当前单元格有效的项目(在这一点上,细胞仍然在它的原始值)。如果输入是无效的,取消参数设置为true,将继续留在格编辑,直到用户输入一个有效的输入模式。
例如,下面的代码验证成货币列输入,以确保输入的值在1000和10000是:
代码示例:
Merged Table Headers(合并表头)
功能描述:要创建合并表头,你必须首先设置网格的AllowMerging属性FixedOnly。然后,指定的行和列要合并设置的行和列的AllowMerging属性。最后,分配到页眉文本细胞,使细胞要合并有相同的内容。
下面的代码显示了一个例子:
代码示例:
This is the result:
Merged Data Views(合并数据)
功能描述:
单元格合并的工作方式相同,当网格绑定到数据源。下面的代码显示了绑定到数据源在设计时一格一个例子。如需绑定到数据源的信息,请参见绑定到数据源。
代码示例:
This is the result:
Creating Subtotals(创建分类汇总)
功能描述:该C1FlexGrid.Subtotal方法将包含在常规(非小计)行的汇总数据汇总行。
小计支援阶层集合体。例如,如果你的网格包含销售数据,您可能获得总销售额合计按产品,区域,和销售人员的数字。下面的代码说明了这一点
代码示例:
当C1FlexGrid.Subtotal方法添加行的汇总信息,它会自动分配小计样式新行(有内置的5个分类汇总级别样式)。您可以通过更改在与风格编辑器或代码设计师的大纲样式属性的分类汇总行的外观。例如:
After executing this code, the grid would look like this:
在总计行中包含的所有产品,地区和销售人员的总销售额。它是一个用在方法调用的C1FlexGrid.Subtotal groupOn参数为-1。另按产品分类汇总显示和地区的总销售额。他们创建的一个值0,为groupOn参数1。
您也可以计算总量比其他款项(例如,平均值或百分比),并计算每行数总量(例如,毛保费及净销售额)。
由小计小计行方法建立在三个方面有所不同规则的行:
1。小计行可以被自动删除通过调用参数与flexSTClear小计方法。这是非常有用的数据提供,用户可以移动列,并重新对数据进行排序,因此有必要重新计算分类汇总的动态视图。
2。小计行可作为节点的一个大纲,让您折叠和展开的行群体提出一个数据概述或透露其细节。要看到树的轮廓,你需要设置列和Tree.Style属性来定义的位置和轮廓树的外观。
3。小计行可以被视为在一个树节点。你可以通过任何节点属性分类汇总行中的节点对象。
4。当网格绑定到数据源,小计行不符合实际的数据。如果你在数据源中的光标,次全行会被忽略在网格中。
大纲树允许用户通过折叠和展开的节点上点击网格的部分。您可以使用大纲树来显示多种类型的信息,不仅总量。下一个主题演示如何创建一个自定义大纲树来显示目录信息。
Creating Custom Trees(创建自定义树)
功能描述:创造轮廓树不使用小结的方法中,你需要遵循这些步骤:
1。添加排电网。
2。把一些行转换成轮廓节点IsNode把他们的财产是真实的。
3。得到节点对象为每个节点排并设置其水平产权界定节点的位置在树上的层次结构。更高的价值意味着节点是更深的(更)为轮廓缩进树。
例如,下面的代码创建一个目录树:
代码示例:
1 // add these using statements at the top of the form 2 3 using System; 4 5 using System.Collections.Generic; 6 7 using System.ComponentModel; 8 9 using System.Data; 10 11 using System.Drawing; 12 13 using System.Text; 14 15 using System.Windows.Forms; 16 17 using System.IO; 18 19 using C1.Win.C1FlexGrid; 20 21 22 23 private void Form1_Load(object sender, EventArgs e) 24 25 { 26 27 28 29 // Initialize grid layout. 30 31 _flex.Cols.Fixed = 0; 32 33 _flex.Cols.Count = 1; 34 35 _flex.Rows.Count = 1; 36 37 _flex.ExtendLastCol = true; 38 39 _flex.Styles.Normal.TextAlign = TextAlignEnum.LeftCenter; 40 41 _flex.Styles.Normal.Border.Style = BorderStyleEnum.None; 42 43 44 45 // Initialize outline tree. 46 47 _flex.Tree.Column = 0; 48 49 _flex.Tree.Style = TreeStyleFlags.SimpleLeaf; 50 51 _flex.Tree.LineColor = Color.DarkBlue; 52 53 54 55 // Populate the grid. 56 57 AddDirectory(@"c:\\", 0); 58 59 }
上面的代码初始化电网布局,并调用AddDirectory例程,并在网格的填充和设立树状结构的工作:
1 private void AddDirectory(string dir, int level) 2 3 { 4 5 // add this directory 6 7 string thisDir = Path.GetFileName(dir); 8 9 if (thisDir.Length == 0) { thisDir = dir; } 10 11 _flex.AddItem(thisDir); 12 13 //make this new row a node 14 15 Row row = _flex.Rows[_flex.Rows.Count - 1]; 16 17 row.IsNode = true; 18 19 //set node level 20 21 Node nd = row.Node; 22 23 nd.Level = level; 24 25 // add files in this directory 26 27 int cnt = 0; 28 29 Row r; 30 31 32 33 foreach (string file in Directory.GetFiles(dir)) 34 35 { 36 37 _flex.AddItem(Path.GetFileName(file).ToLower()); 38 39 //mark the row without child row as node 40 41 r = _flex.Rows[_flex.Rows.Count - 1]; 42 43 r.IsNode = true; 44 45 r.Node.Level = level + 1; 46 47 cnt = cnt + 1; 48 49 if (cnt > 10) break; 50 51 } 52 53 54 55 // add subdirectories (up to level 4) 56 57 if (level <= 4) 58 59 { 60 61 cnt = 0; 62 63 foreach (string subdir in Directory.GetDirectories(dir)) 64 65 { 66 67 AddDirectory(subdir, level + 1); 68 69 cnt = cnt + 1; 70 71 if (cnt > 10) break; 72 73 } 74 75 } 76 77 }
addDirectory是递归的常规的足迹横贯当前目录和子目录。在这个例子中,这棵树大小是有限的四目录水平,从而节省时间。在实际应用中,参赛者应该改变的树枝在只有当他们的扩展(见FlexGrid为WinForms教程)。
这个代码创建了一个网格,看起来像这样:
Creating Outlines and Trees with the C1FlexGrid Control(建立具有C1FlexGrid控制要点和树木)
功能描述:一个独特的和最受欢迎C1FlexGrid控制的特点就是能够添加层次分组常规的非结构化的数据。
要达到这个目标,亚文化的概念C1FlexGrid节点的行。节点行不含定期数据。相反,他们作为标题下,类似的数据的落在了一起,一模一样的节点到普通的树状视图控件。喜欢一个树状视图控件的节点,节点行可以倒塌和扩大,隐藏或显示它们所包含的数据。也喜欢节点到TreeView
一个独特的和最受欢迎的特点C1FlexGrid控制所有的信息就在那里,但是很难看到的总销售每一个国家或客户。你可以使用C1FlexGrid的概述特点,国家(数据组级别0),然后由市在每个国家(一级),然后由客户内部各城市(要求等级2)。这是同一网格以售后增加大纲:
这栅格显示相同的信息作为前势必相同的数据来源),但增加了每个节点树下,包含的数据总结下方。节点可以倒塌,只显示总结,或扩大到显示细节。注意每个节点排可以展现了一个多总结栏(在这种情况下,总单位售出和总多)。
在这篇文章中,我们将送你的整个过程将一个规则的网格成一个更丰富的轮廓的格子。
加载数据输入纲要网格是完全一样的加载到一个规则的网格。如果你的数据来源可在设计阶段,你可以用的v isuals tudio财产的窗口,把财产DataSource网格系统的数据网格不用写代码。
如果数据源是不对外开放的设计时间,你可以设置你的网格系统的财产DataSource代码。数据绑定的代码通常看起来像这样:
1 public Form1() 2 3 { 4 5 InitializeComponent(); 6 7 8 9 // get data 10 11 var fields = @" 12 13 Country, 14 15 City, 16 17 SalesPerson, 18 19 Quantity, 20 21 ExtendedPrice"; 22 23 var sql = string.Format("SELECT {0} FROM Invoices ORDER BY {0}", fields); 24 25 var da = new OleDbDataAdapter(sql, GetConnectionString()); 26 27 da.Fill(_dt); 28 29 30 31 // bind grid to data 32 33 this._flex.DataSource = _dt; 34 35 36 37 // format ExtendedPrice column 38 39 _flex.Cols["ExtendedPrice"].Format = "n2"; 40 41 }
代码使用一个OleDbDataAdapter填补一个DataTable与数据,thenand然后指定DataTable到网格系统的DataSource财产。
运作后这些代码,你将得到”规则格子“第一个图像中所示。将这个规则的网格的网格所显示的轮廓第二形象,我们需要插入节点行组成的轮廓。
Creating Node Rows(创建节点行)
点行规则的行几乎相同,除了以下几点:
•节点行不是数据的约束。当网格绑定到数据源,每届常行对应的数据源中的一个项目。节点的行不。相反,它们的存在组包含相似的数据规则的行。
•节点行可以折叠或展开。当一个节点行倒塌,所有的数据和子节点都被隐藏。如果是可见的轮廓树,用户可以折叠和展开节点使用鼠标或键盘。如果树是不可见的轮廓,然后节点可以展开或折叠只能使用代码。
要确定是否行是一个节点或没有,你可以使用IsNode属性:
1 var row = _flex.Rows[rowIndex]; 2 3 if (row.IsNode) 4 5 { 6 7 // row is a node 8 9 var node = row.Node; 10 11 DoSomethingWithTheNode(node); 12 13 } 14 15 else 16 17 { 18 19 // this row is not a node 20 21 }
节点行可以创建在三个方面:
1。使用Rows.InsertNode方法。这将插入一个新节点指定索引列。一旦节点行已被创建,您可以使用像使用任何其他的行它(为每个列的数据,应用样式等)。这是'低层次'插入总数和建筑轮廓的方法。它使大多数控制和灵活性,表现如下。
2。使用C1FlexGrid.Subtotal方法。这种方法扫描整个网格,并自动插入节点在位置与可选的分类汇总行,其中电网数据的变化。这是'高层次'插入总数和建筑轮廓的方法。它需要非常少的代码,但这样一些数据是如何在赛场上和结构是什么样子大纲应假设。
3。如果格不作承诺,那么你可以打开属性设置为true IsNode行成节点规则的行。请注意,仅当网格绑定。试图把装订成一排普通节点的数据将导致网格抛出一个异常。
下面说明如何可以实现一个GroupBy方法,插入节点的行分组对一个给定列相同的值的代码。
•节点行可以折叠或展开。当一个节点行倒塌,所有的数据和子节点都被隐藏。如果是可见的轮廓树,用户可以折叠和展开节点使用鼠标或键盘。如果树是不可见的轮廓,然后节点可以展开或折叠只能使用代码。
要确定是否行是一个节点或没有,你可以使用IsNode属性:
1 // group on a given column inserting nodes of a given level 2 3 void GroupBy(string columnName, int level) 4 5 { 6 7 object current = null; 8 9 for (int r = _flex.Rows.Fixed; r < _flex.Rows.Count; r++) 10 11 { 12 13 if (!_flex.Rows[r].IsNode) 14 15 { 16 17 var value = _flex[r, columnName]; 18 19 if (!object.Equals(value, current)) 20 21 { 22 23 // value changed: insert node 24 25 _flex.Rows.InsertNode(r, level); 26 27 28 29 // show group name in first scrollable column 30 31 _flex[r, _flex.Cols.Fixed] = value; 32 33 34 35 // update current value 36 37 current = value; 38 39 } 40 41 } 42 43 } 44 45 }
该代码扫描所有列,跳过现有的节点行(所以它可以被调用时,添加不同层次的节点),并保持该列被分组对当前值的轨道。当电流值的变化,一个节点插入一行滚动显示在第一列中的新组的名称。
回到我们的例子,你可以使用此方法来创建调用两个级别的大纲:
1 void _btnGroupCountryCity_Click(object sender, EventArgs e) 2 3 { 4 5 GroupBy("Country", 0); 6 7 GroupBy("City", 1); 8 9 }
很简单,但也有一些注意事项。首先,该方法假定数据进行排序按大纲结构。在这个例子中,如果数据是按销售人员,而不是按国别排序,纲要将有几个0级,每个国家,这可能是不是你想要的节点。
此外,GroupBy方法可能会插入行,这将导致闪烁的网格。为了避免这种情况,你通常会设置的更新,然后才作出虚假重绘财产,并将其设置回True时完成。
为了处理这些问题,代码创建大纲应重新编写如下:
1 void _btnGroupCountryCity_Click(object sender, EventArgs e) 2 3 { 4 5 // suspend redrawing while updating 6 7 using (new DeferRefresh(_flex)) 8 9 { 10 11 // restore original sort (by Country, City, etc.) 12 13 ResetBinding(); 14 15 16 17 // group by Country, City 18 19 GroupBy("Country", 0); 20 21 GroupBy("City", 1); 22 23 } 24 25 }
该DeferRefresh类是一个简单的工具,设置网格的重绘属性为false,恢复其原始值时,处置。这确保了重绘,即使是恢复正常的更新过程中发生异常。这里是DeferRefresh类的实现:
1 /// Utility class used to encapsulate grid lengthy operations in a Redraw block. 2 3 /// This avoids flicker and ensures the Redraw property is reset properly in case 4 5 /// an exception is thrown during the operation. 6 7 class DeferRefresh : IDisposable 8 9 { 10 11 C1FlexGrid _grid; 12 13 bool _redraw; 14 15 public DeferRefresh(C1FlexGrid grid) 16 17 { 18 19 _grid = grid; 20 21 _redraw = grid.Redraw; 22 23 grid.Redraw = false; 24 25 } 26 27 public void Dispose() 28 29 { 30 31 _grid.Redraw = _redraw; 32 33 } 34 35 }
该BindGrid方法确保电网是我们的大纲结构中规定的次序排序。在我们的例子中,排序顺序是由国家,城市,和销售人员。代码看起来是这样的:
1 // unbind and re-bind grid in order to reset everything 2 3 void ResetBinding() 4 5 { 6 7 // unbind grid 8 9 _flex.DataSource = null; 10 11 12 13 // reset any custom sorting 14 15 _dt.DefaultView.Sort = string.Empty; 16 17 18 19 // re-bind grid 20 21 _flex.DataSource = _dt; 22 23 24 25 // format ExtendedPrice column 26 27 _flex.Cols["ExtendedPrice"].Format = "n2"; 28 29 30 31 // auto-size the columns to fit their content 32 33 _flex.AutoSizeCols(); 34 35 }
如果您运行此代码现在,你会发现创建为节点行预期,但轮廓树是不可见的,所以你不能展开和折叠节点。大纲树中的关键部分。
Outline Tree(大纲树)
功能描述:大纲树是非常相似的一个你在一个TreeView控件经常看到的。它显示了一个折叠/展开图标旁边,使用户在每个节点行可以展开和折叠大纲看到所需级别缩进的详细结构。
大纲树可以显示在属性定义的Tree.Column任何列。默认情况下,这个属性被设置为-1,这将导致在所有不被显示的树。要显示在上面,你可以使用此代码所举的例子大纲树:
代码示例:
1 void _btnTreeCountryCity_Click(object sender, EventArgs e) 2 3 { 4 5 using (new DeferRefresh(_flex)) 6 7 { 8 9 // group by country and city as before 10 11 _btnGroupCountryCity_Click(this, EventArgs.Empty); 12 13 14 15 // show outline tree 16 17 _flex.Tree.Column = 0; 18 19 20 21 // autosize to accommodate tree 22 23 _flex.AutoSizeCol(_flex.Tree.Column); 24 25 26 27 // collapse detail nodes 28 29 _flex.Tree.Show(1); 30 31 } 32 33 }
该代码调用以前的方法来建立大纲,thenand然后设置Tree.Column属性设置为零,以显示在第一列提纲树。它还调用C1FlexGrid.AutoSizeCol方法,以确保该列的宽度足以容纳大纲树。最后,它调用Tree.Show方法来显示所有0级节点(在这种情况下市),隐藏所有的细节。
树属性返回一个引用到GridTree对象,公开的几种方法,并用于自定义大纲树属性。主要的有如下:
•列:获取或设置列包含大纲树索引。将此属性设置为-1原因大纲树将隐藏在用户。
•缩进:获取或设置缩进像素,相邻节点之间的水平。水平较高的缩进导致树变宽。
•风格:获取或设置树类型的大纲显示。使用这个属性来判断是否应包括在树的顶部按钮栏,使用户能够折叠/展开整个树,行是否和/或符号应显示,以及是否应显示连接线的数据行的树以及节点行。
•LineColor:获取或设置树的连接线的颜色。
•的LineStyle:获取或设置树的连接线的样式。
例如,通过改变上面的代码包含以下两行:
1 // show outline tree 2 3 _flex.Tree.Column = 0; 4 5 _flex.Tree.Style = TreeStyleFlags.CompleteLeaf; 6 7 _flex.Tree.LineColor = Color.White; 8 9 _flex.Tree.Indent = 30;
请注意按钮标记为“1”,“2”,和“*”的左上角单元格。点击这些按钮会导致整个树折叠或展开相应的水平。还要注意更广泛的压痕线和连接树(“安妮Dodsworth的”)以及节点行定期行。
Adding Subtotals(添加分类别汇总)
功能描述:到目前为止,我们已经覆盖了节点树行和大纲创作。为了使真正有用的轮廓,但是,节点行应包括摘要它们包含的数据信息。
如果您创建一个轮廓树使用C1FlexGrid.Subtotal方法,然后分类汇总会自动添加。这将在后面的章节所述。
如果你创建轮廓树使用Rows.InsertNode方法如上所述,那么你应该直接使用到节点行的C1FlexGrid.Aggregate方法来计算每一组行并插入结果的汇总。
该C1FlexGrid.Subtotal方法列示上市如何做到这一点:
1 // add subtotals to each node at a given level 2 3 void AddSubtotals(int level, string colName) 4 5 { 6 7 // get column we are going to total on 8 9 int colIndex = _flex.Cols.IndexOf(colName); 10 11 12 13 // scan rows looking for nodes at the right level 14 15 for (int r = _flex.Rows.Fixed; r < _flex.Rows.Count; r++) 16 17 { 18 19 if (_flex.Rows[r].IsNode) 20 21 { 22 23 var node = _flex.Rows[r].Node; 24 25 if (node.Level == level) 26 27 { 28 29 // found a node, calculate the sum of extended price 30 31 var range = node.GetCellRange(); 32 33 var sum = _flex.Aggregate(AggregateEnum.Sum, 34 35 range.r1, colIndex, range.r2, colIndex, 36 37 AggregateFlags.ExcludeNodes); 38 39 40 41 // show the sum on the grid 42 43 // (will use the column format automatically) 44 45 _flex[r, colIndex] = sum; 46 47 } 48 49 } 50 51 } 52 53 }
该AddSubtotals方法扫描为节点的网格行的行寻找。当所期望的水平节点行被发现,该方法使用GetCellRange方法检索节点的子行。然后,它使用C1FlexGrid.Aggregate方法来计算在整个范围内对目标列中的值的总和。对总呼叫包括ExcludeNodes标志,以避免重复计算,现有节点。一旦经过计算小计,它被分配到节点行的细胞通常_flex [行,列]索引。
请注意,这并不会影响以任何方式的数据源,因为节点行不绑定到数据。
还要注意,该方法可以用来添加到每个节点的多个总计行。在这个例子中,我们将增加的数量和扩展价格列总数。除了金钱,你可以添加如平均,最高,最低等其他聚合
现在,我们可以使用此方法来创建节点行,轮廓树,一个完整的轮廓和小计:
1 void _btnTreeCountryCity_Click(object sender, EventArgs e) 2 3 { 4 5 using (new DeferRefresh(_flex)) 6 7 { 8 9 // restore original sort (by Country, City, SalesPerson) 10 11 ResetBinding(); 12 13 14 15 // group by Country, City 16 17 GroupBy("Country", 0); // group by country (level 0) 18 19 GroupBy("City", 1); // group by city (level 1) 20 21 22 23 // add totals per Country, City 24 25 AddSubtotals(0, "ExtendedPrice"); // extended price per country (level 0) 26 27 AddSubtotals(0, "Quantity"); // quantity per country (level 0) 28 29 AddSubtotals(1, "ExtendedPrice"); // extended price per city (level 1) 30 31 AddSubtotals(1, "Quantity"); // quantity per city (level 1) 32 33 34 35 // show outline tree 36 37 _flex.Tree.Column = 0; 38 39 _flex.AutoSizeCol(_flex.Tree.Column); 40 41 _flex.Tree.Show(1); 42 43 } 44 45 }
如果您运行该项目现在,你会看到一个与该节目的总数量和每个国家和城市节点销售金额排树。这是非常好的,但有一个小问题。如果展开的节点任何行,你会看到许多重复的值。根据给定的城市节点的所有行具有相同的国家和城市:
这是正确的,但它也是一个屏幕房地产的浪费。消除这些重复的值很容易,你需要做的就是设置正在分组到零列的宽度。当你这样做,但是,你要记得设置网格的AllowMerging属性节点,因此分配给该节点行的文本将波及到可见列。 (另一个选择是将文本的节点分配到第一个可见列,但合并通常是更好的解决方案,因为它可以让你用更长的时间节点行文本)。
下面是修改后的代码和最后的结果:
1 void _btnTreeCountryCity_Click(object sender, EventArgs e) 2 3 { 4 5 using (new DeferRefresh(_flex)) 6 7 { 8 9 // restore original sort (by Country, City, SalesPerson) 10 11 ResetBinding(); 12 13 14 15 // group by Country, City 16 17 GroupBy("Country", 0); // group by country (level 0) 18 19 GroupBy("City", 1); // group by city (level 1) 20 21 22 23 // hide columns that we grouped on 24 25 // (they only have duplicate values which already appear on the tree nodes) 26 27 // (but don't make them invisible, that would also hide the node text) 28 29 _flex.Cols["Country"].Width = 0; 30 31 _flex.Cols["City"].Width = 0; 32 33 34 35 // allow node content to spill onto next cell 36 37 _flex.AllowMerging = AllowMergingEnum.Nodes; 38 39 40 41 // add totals per Country, City 42 43 AddTotals(0, "ExtendedPrice"); // extended price per country (level 0) 44 45 AddTotals(0, "Quantity"); // quantity per country (level 0) 46 47 AddTotals(1, "ExtendedPrice"); // extended price per city (level 1) 48 49 AddTotals(1, "Quantity"); // quantity per city (level 1) 50 51 52 53 // show outline tree 54 55 _flex.Tree.Column = 0; 56 57 _flex.AutoSizeCol(_flex.Tree.Column); 58 59 _flex.Tree.Show(1); 60 61 } 62 63 }
Using the Subtotal Method(使用小计法)
功能描述:我们提到过,你也可以使用C1FlexGrid创建树的C1FlexGrid.Subtotal方法。 TheSubtotal方法执行的GroupBy和AddSubtotals方法上述相同的任务,除非它在一个单一的步骤,因此这两种东西多一点效率。
下面显示了如何使用分类汇总方法的代码来完成相同的事情,我们过了,只是快一点,没有使用任何辅助方法做的:
1 void _btnTreeCountryCity_Click(object sender, EventArgs e) 2 3 { 4 5 using (new DeferRefresh(_flex)) 6 7 { 8 9 // restore original sort (by Country, City, SalesPerson) 10 11 ResetBinding(); 12 13 14 15 // group and total by country and city 16 17 _flex.Subtotal(AggregateEnum.Sum, 0, "Country", "ExtendedPrice"); 18 19 _flex.Subtotal(AggregateEnum.Sum, 0, "Country", "Quantity"); 20 21 _flex.Subtotal(AggregateEnum.Sum, 1, "City", "ExtendedPrice"); 22 23 _flex.Subtotal(AggregateEnum.Sum, 1, "City", "Quantity"); 24 25 26 27 // hide columns that we grouped on 28 29 // (they only have duplicate values which already appear on the tree nodes) 30 31 // (but don't make them invisible, that would also hide the node text) 32 33 _flex.Cols["Country"].Width = 0; 34 35 _flex.Cols["City"].Width = 0; 36 37 _flex.AllowMerging = AllowMergingEnum.Nodes; 38 39 40 41 // show outline tree 42 43 _flex.Tree.Column = 0; 44 45 _flex.AutoSizeCol(_flex.Tree.Column); 46 47 _flex.Tree.Show(1); 48 49 } 50 51 }
分类汇总的方法是非常方便和灵活。它有一个重载允许您指定的列进行分组并总计由索引或名称,是否包含列标题的节点中插入的是,如何进行分组和数量等。下面摘要介绍了重载版本:
1。小计(AggregateEnum aggType)
这个版本的方法只需要一个聚合类型作为参数。它是有用的,只有去除,然后再插入新的现有的分类汇总。在这种情况下,aggType参数设置为AggregateEnum.Clear。
2。小计(AggregateEnum aggType,诠释groupBy,诠释totalOn)
小计(AggregateEnum aggType,字符串groupBy,字符串totalOn)
这些是最常用的重载。该参数是要插入的聚合类型和对本集团的总列上。被引用的列可以通过索引或名称。后者是一个我们在上面的例子使用。
3。小计(AggregateEnum aggType,诠释groupBy,诠释totalOn,字符串标题)
小计(AggregateEnum aggType,字符串groupBy,字符串totalOn,串标题)
这些重载标题添加一个额外的参数。标题参数确定被添加到新节点的行被分组确定价值的文本。默认情况下,该值被分为上显示出来,所以如果你是按国家分组时,节点的行会显示“阿根廷”,“巴西”,等等。如果您设置标题参数为字符串,如“国家:{0}”,则节点的行会显示“国家:阿根廷”代替。
4。小计(AggregateEnum aggType,诠释groupFrom,诠释groupTo,诠释totalOn,字符串标题)
小计(AggregateEnum aggType,字符串groupFrom,字符串groupTo,字符串totalOn,串标题)
这些重载groupBy分成两个参数:groupFrom和groupTo。默认情况下,小计方法插入一个节点,只要行的groupBy或前一列的值更改。
例如,如果你行已在“城市”为前行的列值相同,但是在“国家”一栏,不同的值,然后分类汇总方法假设行应在不同的组,并插入一个新节点即使排在groupBy列的值是相同的。这些总量让你重写该行为,并指定时,应考虑确定一个组列的范围。
Using the Node class(使用节点类)
功能描述:Node类提供的方法和可用于创建和管理大纲树属性。这些方法和属性很多是基于标准的TreeView的对象模型,因此他们应该最熟悉的开发人员。
要获得一个节点对象,你可以:
使用该方法的返回值Rows.InsertNode:
var node = _flex.Rows.InsertNode(index, level);
或者你可以为现有的检索使用行的节点属性行节点:
var node = _flex.Rows[index].IsNode
? _flex.Rows[index].Node
: null;
无论哪种方式,一旦你有一个节点对象,你可以对其进行操作使用下列属性和方法:
•等级:获取或设置在树节点级别的大纲。
•数据:获取或设置由Node.Row和Tree.Column定义的单元格的值。
•图像:获取或设置由Node.Row和Tree.Column定义的细胞图像。
•选中:获取或设置由Node.Row和Tree.Column定义的细胞检查状态。
•折叠/展开:获取或设置节点的折叠/展开状态。
您还可以探索大纲结构使用以下方法:
•GetCellRange():获取一个CellRange对象,描述了属于此列节点范围。
•儿童:获取此节点下的子节点的数目。
•节点:节点阵列获取一个包含此节点的子节点。
•GetNode:获取节点,有一个给定的关系到该节点(父,第一个孩子,一个兄弟,等)。
上述讨论的约束情况下,这里的电网是连接到数据源,提供了数据集中。您还可以创建未绑定的情况下树木和轮廓。其实有些事情是在这种情况下更简单,因为你可以变成一个节点行通过设置IsNode属性为true任何行。
如果格不作承诺,它拥有所有显示的数据,你做的事情是不可能的,当一个数据源拥有数据。例如,你可以移动使用移动方法,通过与C1FlexGrid提供TreeNode的样本显示树节点。
使用未绑定的网格节点非常相似,在常规使用TreeView控件的节点。