@@ -22,94 +22,241 @@ If there are items for a certain node, it will have an expand icon. The `HasChil
2222```` CSHTML
2323@* Hierarchical data items hold collections of the child items *@
2424
25- <TelerikTreeList Data="@Data"
26-
27- ItemsField="@(nameof(Employee.DirectReports))"
28-
29- Pageable="true" Width="850px">
30- <TreeListColumns>
31- <TreeListColumn Field="Name" Expandable="true" Width="320px" />
32- <TreeListColumn Field="Id" Editable="false" Width="120px" />
33- <TreeListColumn Field="EmailAddress" Width="220px" />
34- <TreeListColumn Field="HireDate" Width="220px" />
35- </TreeListColumns>
36- </TelerikTreeList>
25+ <TelerikGantt Data="@Data"
26+ Width="100%"
27+ Height="600px"
28+ ItemsField="Items"
29+ OnCreate="@CreateItem"
30+ OnUpdate="@UpdateItem"
31+ OnDelete="@DeleteItem"
32+ Sortable="true"
33+ SortMode="@SortMode.Multiple"
34+ FilterMode="@GanttFilterMode.FilterMenu"
35+ FilterMenuType="@FilterMenuType.Menu">
36+ <GanttToolBar>
37+ <GanttCommandButton Command="Add" Icon="add">Add</GanttCommandButton>
38+ </GanttToolBar>
39+ <GanttViews>
40+ <GanttDayView></GanttDayView>
41+ <GanttWeekView></GanttWeekView>
42+ <GanttMonthView></GanttMonthView>
43+ <GanttYearView></GanttYearView>
44+ </GanttViews>
45+ <GanttColumns>
46+ <GanttCommandColumn>
47+ <GanttCommandButton Command="Add" Icon="add"></GanttCommandButton>
48+ <GanttCommandButton Command="Delete" Icon="delete"></GanttCommandButton>
49+ </GanttCommandColumn>
50+ <GanttColumn Field="Id"
51+ Visible="false">
52+ </GanttColumn>
53+ <GanttColumn Field="Title"
54+ Expandable="true"
55+ Width="160px"
56+ Title="Task Title">
57+ </GanttColumn>
58+ <GanttColumn Field="PercentComplete"
59+ Width="100px">
60+ </GanttColumn>
61+ <GanttColumn Field="Start"
62+ Width="200px"
63+ TextAlign="@ColumnTextAlign.Right">
64+ </GanttColumn>
65+ <GanttColumn Field="End"
66+ DisplayFormat="End: {0:d}"
67+ Width="200px">
68+ </GanttColumn>
69+ </GanttColumns>
70+ </TelerikGantt>
3771
3872@code {
39- public List<Employee> Data { get; set; }
40-
41- // sample model
73+ public DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0);
4274
43- public class Employee
75+ class HierarchicalModel
4476 {
45- // hierarchical data collections
46- public List<Employee> DirectReports { get; set; }
47-
48- // data fields for display
4977 public int Id { get; set; }
50- public string Name { get; set; }
51- public string EmailAddress { get; set; }
52- public DateTime HireDate { get; set; }
78+ public List<HierarchicalModel> Items { get; set; }
79+ public HierarchicalModel Parent { get; set; }
80+ public string Title { get; set; }
81+ public double PercentComplete { get; set; }
82+ public DateTime Start { get; set; }
83+ public DateTime End { get; set; }
5384 }
5485
55- // data generation
56-
57- // used in this example for data generation and retrieval for CUD operations on the current view-model data
5886 public int LastId { get; set; } = 1;
5987
60- protected override async Task OnInitializedAsync()
61- {
62- Data = await GetTreeListData();
63- }
88+ List<HierarchicalModel> Data { get; set; }
6489
65- async Task<List<Employee>> GetTreeListData ()
90+ protected override void OnInitialized ()
6691 {
67- List<Employee> data = new List<Employee >();
92+ Data = new List<HierarchicalModel >();
6893
69- for (int i = 1; i < 15 ; i++)
94+ for (int i = 1; i < 6 ; i++)
7095 {
71- Employee root = new Employee
96+ var newItem = new HierarchicalModel()
7297 {
7398 Id = LastId,
74- Name = $"root: {i}",
75- EmailAddress = $"{i}@example.com",
76- HireDate = DateTime.Now.AddYears(-i),
77- DirectReports = new List<Employee>(), // prepare a collection for the child items, will be populated later in the code
99+ Items = new List<HierarchicalModel>(),
100+ Title = "Employee " + i.ToString(),
101+ Start = new DateTime(2020, 12, 6 + i),
102+ End = new DateTime(2020, 12, 11 + i),
103+ PercentComplete = i * 0.125
78104 };
79- data.Add(root);
105+
106+ Data.Add(newItem);
80107 LastId++;
81108
82- for (int j = 1 ; j < 4 ; j++)
109+ for (int j = 0 ; j < 5 ; j++)
83110 {
84- int currId = LastId;
85- Employee firstLevelChild = new Employee
111+ newItem.Items.Add(new HierarchicalModel()
86112 {
87- Id = currId,
88- Name = $"first level child {j} of {i}",
89- EmailAddress = $"{currId}@example.com",
90- HireDate = DateTime.Now.AddDays(-currId),
91- DirectReports = new List<Employee>(), // collection for child nodes
92- };
93- root.DirectReports.Add(firstLevelChild); // populate the parent's collection
113+ Id = LastId,
114+ Title = " Employee " + i + " : " + j.ToString(),
115+ Start = new DateTime(2020, 12, 6 + i + j),
116+ End = new DateTime(2020, 12, 7 + i + j),
117+ PercentComplete = j * 0.225,
118+ Parent = newItem
119+ });
120+
94121 LastId++;
122+ }
123+ }
124+ }
125+
126+ private void CreateItem(GanttCreateEventArgs args)
127+ {
128+ var argsItem = args.Item as HierarchicalModel;
129+
130+ argsItem.Id = LastId++;
131+
132+ if (args.ParentItem != null)
133+ {
134+ var parent = (HierarchicalModel)args.ParentItem;
135+
136+ if (parent.Items == null)
137+ {
138+ parent.Items = new List<HierarchicalModel>();
139+ }
140+
141+ parent.Items.Add(argsItem);
142+
143+ argsItem.Parent = parent;
144+
145+ CalculateParentPercentRecursive(parent);
146+ CalculateParentRangeRecursive(parent);
147+ }
148+ else
149+ {
150+ Data.Insert(0, argsItem);
151+ }
152+ }
153+
154+ private void UpdateItem(GanttUpdateEventArgs args)
155+ {
156+ var item = args.Item as HierarchicalModel;
157+
158+ var foundItem = FindItemRecursive(Data, item.Id);
159+
160+ if (foundItem != null)
161+ {
162+ var startOffset = item.Start - foundItem.Start;
163+ if (startOffset != TimeSpan.Zero && foundItem.Items != null)
164+ {
165+ MoveChildrenRecursive(foundItem, startOffset);
166+ }
167+
168+ foundItem.Title = item.Title;
169+ foundItem.Start = item.Start;
170+ foundItem.End = item.End;
171+ foundItem.PercentComplete = item.PercentComplete;
172+
173+ if (foundItem.Parent != null)
174+ {
175+ CalculateParentPercentRecursive(foundItem.Parent);
176+ CalculateParentRangeRecursive(foundItem.Parent);
177+ }
178+ }
179+ }
180+
181+ private void DeleteItem(GanttDeleteEventArgs args)
182+ {
183+ var item = FindItemRecursive(Data, (args.Item as HierarchicalModel).Id);
184+
185+ if (item.Parent != null)
186+ {
187+ item.Parent.Items.Remove(item);
188+
189+ CalculateParentPercentRecursive(item.Parent);
190+ CalculateParentRangeRecursive(item.Parent);
191+ }
192+ else
193+ {
194+ Data.Remove(item);
195+ }
196+ }
197+
198+ private void CalculateParentPercentRecursive(HierarchicalModel item)
199+ {
200+ if (item.Items != null && item.Items.Any())
201+ {
202+ item.PercentComplete = item.Items.Average(i => i.PercentComplete);
203+
204+ if (item.Parent != null)
205+ {
206+ CalculateParentPercentRecursive(item.Parent);
207+ }
208+ }
209+ }
210+
211+ private void CalculateParentRangeRecursive(HierarchicalModel item)
212+ {
213+ if (item.Items != null && item.Items.Any())
214+ {
215+ item.Start = item.Items.Min(i => i.Start);
216+ item.End = item.Items.Max(i => i.End);
217+
218+ if (item.Parent != null)
219+ {
220+ CalculateParentRangeRecursive(item.Parent);
221+ }
222+ }
223+ }
224+
225+ private void MoveChildrenRecursive(HierarchicalModel parent, TimeSpan offset)
226+ {
227+ foreach (var item in parent.Items)
228+ {
229+ item.Start = item.Start.Add(offset);
230+ item.End = item.End.Add(offset);
231+
232+ if (item.Items != null)
233+ {
234+ MoveChildrenRecursive(item, offset);
235+ }
236+ }
237+ }
238+
239+ private HierarchicalModel FindItemRecursive(List<HierarchicalModel> items, int id)
240+ {
241+ foreach (var item in items)
242+ {
243+ if (item.Id.Equals(id))
244+ {
245+ return item;
246+ }
247+
248+ if (item.Items?.Count > 0)
249+ {
250+ var childItem = FindItemRecursive(item.Items, id);
95251
96- for (int k = 1; k < 3; k++ )
252+ if (childItem != null )
97253 {
98- int nestedId = LastId;
99- // populate the parent's collection
100- firstLevelChild.DirectReports.Add(new Employee
101- {
102- Id = LastId,
103- Name = $"second level child {k} of {j} and {i}",
104- EmailAddress = $"{nestedId}@example.com",
105- HireDate = DateTime.Now.AddMinutes(-nestedId)
106- }); ;
107- LastId++;
254+ return childItem;
108255 }
109256 }
110257 }
111258
112- return await Task.FromResult(data) ;
259+ return null ;
113260 }
114261}
115262````
0 commit comments