One of the unique and popular features of the FlexGrid control is the ability to add hierarchical grouping to regular data grid and display it in a tree like structure called TreeGrid. TreeGrid is quite similar to the TreeView control. It shows an indented structure with collapse or expand icon next to each node row so the user can expand and collapse the outline to see the desired level of detail by clicking on the nodes.
TreeGrid helps you implement more advanced use cases such as displaying hierarchical structure of tasks, where each task can have sub-tasks, allowing a detailed breakdown of project work. This kind of organization is common in project management and software development to manage complex projects effectively.
FlexGrid provides ChildItemsPath property that allows you to create a hierarchical structure of data to create a collapsible tree structure. It also provides the following properties based on TreeView object model, which can be used to manage TreeGrid.
Properties | Description |
---|---|
TreeExpandMode | Indicates how the tree is loaded and displayed in the grid. By default, this property has the GridTreeExpandMode.OnDemand value, meaning the tree is initially collapsed, and the subtrees are loaded on demand as the parent’s get expanded. This is the fastest mode to load, and is very useful for scenarios where the ChildItemsPath property is pointing to a late-evaluated property or huge trees. For other scenarios it can be useful or required the tree to be expanded from scratch. To make this you can simply set TreeExpandMode to Expanded mode and the whole tree is evaluated at loading time and all its nodes are expanded by default. Similarly, there is the Collapsed mode, which evaluates the whole tree and creates all the rows at loading time, but it shows all the nodes of the tree collapsed. |
TreeColumnIndex | Allows you to specify the index of the column that shows the toggle buttons. By default it will be zero, meaning the first column will show the buttons and -1 can be set to avoid showing the buttons. |
TreeIndent | Enables you to specify the length of the indentation displayed in the cells whose columns correspond to the TreeColumnIndex. |
To implement TreeGrid in a FlexGrid control, perform the following steps:
C# |
コードのコピー
|
---|---|
public class ProjectTask : INotifyPropertyChanged { private bool _isExpanded = true; public ProjectTask() { SubTasks = new List<ProjectTask>(); IsExpanded = true; } public string WBS { get; set; } [Display(Name = "タスク名")] public string Name { get; set; } public TimeSpan Duration { get; set; } public DateTime Start { get; set; } public DateTime Finish { get { return Start + Duration; } } [Display(AutoGenerateField = false)] public ProjectTask ParentTask { get; set; } [Display(AutoGenerateField = false)] public List<ProjectTask> SubTasks { get; set; } [Display(AutoGenerateField = false)] public bool IsExpanded { get { return _isExpanded; } set { _isExpanded = value; OnPropertyChanged(); OnIsVisibleChanged(); } } private void OnIsVisibleChanged() { OnPropertyChanged("IsVisible"); foreach (var subTask in SubTasks) { subTask.OnIsVisibleChanged(); } } [Display(AutoGenerateField = false)] public bool IsVisible { get { if (ParentTask == null) { return true; } else if (!ParentTask.IsExpanded) { return false; } else { return ParentTask.IsVisible; } } } [Display(AutoGenerateField = false)] public int Level { get { if (ParentTask == null) { return 0; } else { return ParentTask.Level + 1; } } } #region INotifyPropertyChanged Members private void OnPropertyChanged([CallerMemberName] string propertyName = null) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; |
C# |
コードのコピー
|
---|---|
var task1 = new ProjectTask() { WBS = "1", Name = "要求", Duration = new TimeSpan(50, 0, 0, 0), Start = new DateTime(2009, 12, 4) }; var task11 = new ProjectTask() { WBS = "1.1", Name = "分析", Duration = new TimeSpan(38, 3, 0, 0), Start = new DateTime(2009, 12, 4), ParentTask = task1 }; var task111 = new ProjectTask() { WBS = "1.1.1", Name = "オンライン予約の分析", Duration = new TimeSpan(12, 12, 0, 0), Start = new DateTime(2009, 12, 4), ParentTask = task11 }; var task112 = new ProjectTask() { WBS = "1.1.2", Name = "クエリプロセスの分析", Duration = new TimeSpan(12, 12, 0, 0), Start = new DateTime(2009, 12, 4), ParentTask = task11 }; var task113 = new ProjectTask() { WBS = "1.1.3", Name = "マルチメディアの強化分析", Duration = new TimeSpan(12, 12, 0, 0), Start = new DateTime(2010, 1, 4), ParentTask = task11 }; var task114 = new ProjectTask() { WBS = "1.1.4", Name = "暫定要求の草案作成", Duration = new TimeSpan(5, 0, 0, 0), Start = new DateTime(2010, 1, 14), ParentTask = task11 }; var task115 = new ProjectTask() { WBS = "1.1.5", Name = "事前要件のレビュー", Duration = new TimeSpan(2, 12, 0, 0), Start = new DateTime(2010, 1, 14), ParentTask = task11 }; task11.SubTasks = new List<ProjectTask> { task111, task112, task113, task114, task115 }; var task12 = new ProjectTask() { WBS = "1.2", Name = "受け入れテスト計画", Duration = new TimeSpan(12, 3, 0, 0), Start = new DateTime(2010, 6, 23), ParentTask = task1 }; var task121 = new ProjectTask() { WBS = "1.2.1", Name = "受け入れテスト計画の作成", Duration = new TimeSpan(5, 2, 0, 0), Start = new DateTime(2010, 6, 23), ParentTask = task12 }; var task122 = new ProjectTask() { WBS = "1.2.2", Name = "受け入れテスト計画の草案作成", Duration = new TimeSpan(5, 0, 0, 0), Start = new DateTime(2010, 6, 23), ParentTask = task12 }; task12.SubTasks = new List<ProjectTask> { task121, task122 }; task1.SubTasks = new List<ProjectTask> { task11, task12 }; var task2 = new ProjectTask() { WBS = "2", Name = "設計", Duration = new TimeSpan(55, 0, 0, 0), Start = new DateTime(2010, 8, 12) }; var task21 = new ProjectTask() { WBS = "2.1", Name = "トップレベル設計", Duration = new TimeSpan(27, 12, 0, 0), Start = new DateTime(2010, 8, 12), ParentTask = task2 }; var task211 = new ProjectTask() { WBS = "2.1.1", Name = "オンライン予約の設計", Duration = new TimeSpan(10, 0, 0, 0), Start = new DateTime(2010, 9, 7), ParentTask = task21 }; var task212 = new ProjectTask() { WBS = "2.1.2", Name = "クエリプロセスの設計", Duration = new TimeSpan(10, 12, 0, 0), Start = new DateTime(2010, 9, 14), ParentTask = task21 }; var task213 = new ProjectTask() { WBS = "2.1.3", Name = "マルチメディア強化の設計", Duration = new TimeSpan(10, 6, 0, 0), Start = new DateTime(2010, 10, 4), ParentTask = task21 }; task21.SubTasks = new List<ProjectTask> { task211, task212, task213 }; var task22 = new ProjectTask() { WBS = "2.2", Name = "詳細設計", Duration = new TimeSpan(23, 0, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task2 }; var task221 = new ProjectTask() { WBS = "2.2.1", Name = "設計仕様書の草案作成", Duration = new TimeSpan(17, 12, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task22 }; var task222 = new ProjectTask() { WBS = "2.2.2", Name = "設計仕様書のレビュー", Duration = new TimeSpan(17, 0, 0, 0), Start = new DateTime(2010, 12, 8), ParentTask = task22 }; task22.SubTasks = new List<ProjectTask> { task221, task222 }; task2.SubTasks = new List<ProjectTask> { task21, task22 }; var task3 = new ProjectTask() { WBS = "3", Name = "コードと単体テスト", Duration = new TimeSpan(32, 4, 0, 0), Start = new DateTime(2010, 12, 4) }; var task31 = new ProjectTask() { WBS = "3.1", Name = "開発スタッフの割り当て", Duration = new TimeSpan(2, 3, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task3 }; var task32 = new ProjectTask() { WBS = "3.2", Name = "コードの開発", Duration = new TimeSpan(10, 3, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task3 }; var task321 = new ProjectTask() { WBS = "3.2.1", Name = "オンライン予約の開発", Duration = new TimeSpan(10, 2, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task32 }; var task322 = new ProjectTask() { WBS = "3.2.2", Name = "オンライン予約のテスト", Duration = new TimeSpan(1, 11, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task32 }; var task323 = new ProjectTask() { WBS = "3.2.3", Name = "クエリプロセスの開発", Duration = new TimeSpan(10, 0, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task32 }; var task324 = new ProjectTask() { WBS = "3.2.4", Name = "クエリプロセスのテスト", Duration = new TimeSpan(1, 4, 0, 0), Start = new DateTime(2010, 12, 4), ParentTask = task32 }; task32.SubTasks = new List<ProjectTask> { task321, task322, task323, task324 }; task3.SubTasks = new List<ProjectTask> { task31, task32 }; var tasks = new List<ProjectTask> { task1, task2, task3 }; grid.ItemsSource = tasks; grid.CollapseGroups(3); |
C# |
コードのコピー
|
---|---|
private void OnAutoGeneratingColumn(object sender, C1.Maui.Grid.GridAutoGeneratingColumnEventArgs e) { if (e.Property.Name == "名前") { e.Column.AllowResizing = false; e.Column.MinWidth = 300; e.Column.Width = new GridLength(1, GridUnitType.Star); } if (e.Property.Name == "WBS") e.Column.Width = GridLength.Auto; if (e.Column is GridDateTimeColumn) e.Column.Format = "日/月/年"; } |
XAML |
コードのコピー
|
---|---|
<c1:FlexGrid x:Name="grid" AutoGeneratingColumn="OnAutoGeneratingColumn" AllowFiltering="False" AllowSorting="False" IsReadOnly="True" ChildItemsPath="SubTasks" TreeColumnIndex="1"/> |
The TreeGrid control includes sorting capabilities for efficiently organizing data. You can easily sort data at runtime in a TreeGrid using the column header menu. Sorting in the TreeGrid ensures that not only the parent nodes are organized but also the child nodes follow the same order while maintaining their parent-child relationships. This keeps the hierarchical structure intact.
By default, sorting is enabled in the TreeGrid. However, you can use the AllowSorting property of the FlexGrid class to enable or disable sorting in the TreeGrid. The following code example demonstrates how you can set the AllowSorting property: