I am trying to create a hierarchy grid where the child template columns line up with the parent template columns.
To achieve this I am setting the width of the first column based on the hierarchy level. I've found that a drop in 19 pixels makes up for the expander on the left of the row. The other columns I have set dynamically based upon their parent column widths so that users can resize the grid and the columns will still fill the space.
The issue I am having is on initial load of the grid the columns get jumbled up. However, after a user expands or collapses one of the columns everything lines up and works. (See attached image).
Is there another way to achieve this that ensures that the child column are always lined up with the parent column widths?
To achieve this I am setting the width of the first column based on the hierarchy level. I've found that a drop in 19 pixels makes up for the expander on the left of the row. The other columns I have set dynamically based upon their parent column widths so that users can resize the grid and the columns will still fill the space.
The issue I am having is on initial load of the grid the columns get jumbled up. However, after a user expands or collapses one of the columns everything lines up and works. (See attached image).
Is there another way to achieve this that ensures that the child column are always lined up with the parent column widths?
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using Telerik.WinControls.UI;namespace HierarchyGridExample{ public partial class Form1 : Form { List<MyObject> GridData = new List<MyObject>(); int count = 1; public Form1() { InitializeComponent(); grid.CellValueChanged += grid_CellValueChanged; grid.ColumnWidthChanged += grid_ColumnWidthChanged; grid.ChildViewExpanding += grid_ChildViewExpanding; grid.MultiSelect = true; grid.SelectionMode = GridViewSelectionMode.FullRowSelect; GridViewTemplate level2 = new GridViewTemplate(), level3 = new GridViewTemplate(); CreateTemplate(grid.MasterTemplate); CreateTemplate(level2); CreateTemplate(level3); level2.ShowColumnHeaders = false; level3.ShowColumnHeaders = false; grid.MasterTemplate.Templates.Add(level2); level2.Templates.Add(level3); GridViewRelation rel1 = new GridViewRelation(grid.MasterTemplate, level2); rel1.ChildColumnNames.Add("Children"); grid.Relations.Add(rel1); GridViewRelation rel2 = new GridViewRelation(level2, level3); rel2.ChildColumnNames.Add("Children"); grid.Relations.Add(rel2); /*CreateTemplate(grid.MasterTemplate); GridViewTemplate template = new GridViewTemplate(); CreateTemplate(template); grid.MasterTemplate.Templates.Add(template); template.ShowFilteringRow = false; // Setup child relation GridViewRelation relation = new GridViewRelation(grid.MasterTemplate, template); relation.RelationName = "Children"; relation.ChildColumnNames.Add("TopChildren"); grid.Relations.Add(relation); CreateChildTemplate(template, 0);*/ LoadData(true); grid.MasterTemplate.ExpandAll(); } #region Editing void grid_CellValueChanged(object sender, GridViewCellEventArgs e) { if (e.Column.Name == "Enabled") { (e.Row.DataBoundItem as MyObject).Enabled = (bool)e.Value; } } #endregion Editing #region Formatting private void grid_CellFormatting(object sender, CellFormattingEventArgs e) { if (e.Column.Name == "HLevel") { e.CellElement.Text = e.Row.HierarchyLevel.ToString(); } if (e.Column.Name == "Name") { /*e.CellElement.TextImageRelation = TextImageRelation.ImageBeforeText; e.CellElement.TextAlignment = ContentAlignment.MiddleLeft; e.CellElement.ImageAlignment = ContentAlignment.MiddleLeft; e.CellElement.Image = Properties.Resources.Radio;*/ if (e.Row.HierarchyLevel == 0 && e.Column.Width != 150) { e.Column.Width = 150; e.Column.MaxWidth = 150; e.Column.MinWidth = 150; } else if (e.Column.Width != 131 && e.Row.HierarchyLevel > 0) { e.Column.Width = 131; e.Column.MaxWidth = 131; e.Column.MinWidth = 131; } } else { e.CellElement.Image = null; } } private void grid_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e) { if (e.ColumnIndex > 0) { int masterWidth = grid.MasterTemplate.Columns[e.ColumnIndex].Width; int child1Width = grid.MasterTemplate.Templates[0].Columns[e.ColumnIndex].Width; int child2Width = grid.MasterTemplate.Templates[0].Templates[0].Columns[e.ColumnIndex].Width; if (masterWidth != child1Width) { grid.MasterTemplate.Templates[0].Columns[e.ColumnIndex].Width = masterWidth; //grid.MasterTemplate.Templates[0].Refresh(); } if (masterWidth != child2Width) { grid.MasterTemplate.Templates[0].Templates[0].Columns[e.ColumnIndex].Width = masterWidth; //grid.MasterTemplate.Templates[0].Templates[0].Refresh(); } } } #endregion Formatting #region Expand private void grid_ChildViewExpanding(object sender, ChildViewExpandingEventArgs e) { if (!e.IsExpanded && e.ParentRow.ChildRows.Any()) { List<GridViewTemplate> temps = new List<GridViewTemplate>(); if (grid.MasterTemplate.Templates.Any()) { temps.Add(grid.MasterTemplate.Templates[0]); if (grid.MasterTemplate.Templates[0].Templates.Any()) { temps.Add(grid.MasterTemplate.Templates[0].Templates[0]); } } for (int x = 1; x < grid.MasterTemplate.Columns.Count; x++) { temps.ForEach(c => c.Columns[x].Width = grid.MasterTemplate.Columns[x].Width); } } } private void RestoreExpanded(GridViewRowInfo g, HashSet<object> expanded) { using (grid.DeferRefresh()) { if (g == null) { foreach (var item in this.grid.Rows) { if (expanded.Contains(item.DataBoundItem)) { item.IsExpanded = true; } foreach (var child in item.ChildRows) { RestoreExpanded(child, expanded); } } } else { if (expanded.Contains(g.DataBoundItem)) { g.IsExpanded = true; } foreach (var child in g.ChildRows) { RestoreExpanded(child, expanded); } } } } private void SaveExpanded(GridViewRowInfo g, HashSet<object> items) { if (g == null) { foreach (var item in this.grid.Rows) { if (item.IsExpanded) { items.Add(item.DataBoundItem); } foreach (var child in item.ChildRows) { SaveExpanded(child, items); } } } else { if (g.IsExpanded) { items.Add(g.DataBoundItem); } foreach (var child in g.ChildRows) { SaveExpanded(child, items); } } } #endregion Expand #region Data private void LoadData(bool createTestData = false) { using (grid.DeferRefresh()) { HashSet<object> expanded = new HashSet<object>(); SaveExpanded(null, expanded); grid.DataSource = null; if (createTestData) { GridData = new List<MyObject>(); MyObject m1 = new MyObject("Test " + count); count++; LoadChild(m1, 3); GridData.Add(m1); MyObject m2 = new MyObject("Test " + count); count++; LoadChild(m2, 3); GridData.Add(m2); MyObject m3 = new MyObject("Test " + count); count++; LoadChild(m3, 3); GridData.Add(m3); } grid.DataSource = GridData; RestoreExpanded(null, expanded); } } private void LoadChild(MyObject parent, int number, int level = 0) { level++; for (int i = 0; i < number; i++) { MyObject m2 = new MyObject("Test " + count, count % 2 == 0); count++; parent.Children.Add(m2); m2.Parent = parent; if (level < 2) { LoadChild(m2, number, level); } } } private void CreateChild(MyObject parent = null) { if (parent != null) { MyObject m2 = new MyObject("Test " + count, count % 2 == 0); count++; parent.Children.Add(m2); m2.Parent = parent; //parent.Children.ResetBindings(); } else { MyObject m2 = new MyObject("Test " + count, count % 2 == 0); count++; GridData.Add(m2); } LoadData(); } #endregion Data #region Template private void CreateTemplate(GridViewTemplate t, bool isMaster = false) { t.Columns.Clear(); t.AutoGenerateColumns = false; t.ShowFilteringRow = false; t.EnableGrouping = false; t.AllowAddNewRow = false; t.EnableFiltering = true; t.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill; GridViewTextBoxColumn colName = new GridViewTextBoxColumn("Name"); colName.HeaderText = "Name"; colName.Name = "Name"; t.Columns.Add(colName); GridViewTextBoxColumn colH = new GridViewTextBoxColumn(); colH.HeaderText = "H Level"; colH.Name = "HLevel"; colH.ReadOnly = true; t.Columns.Add(colH); GridViewCheckBoxColumn colEnabled = new GridViewCheckBoxColumn("Enabled"); colEnabled.HeaderText = "Enabled"; colEnabled.Name = "Enabled"; t.Columns.Add(colEnabled); GridViewTextBoxColumn col4 = new GridViewTextBoxColumn(); col4.HeaderText = "Col 4"; col4.Name = "Col4"; col4.ReadOnly = true; t.Columns.Add(col4); } private void CreateChildTemplate(GridViewTemplate parent, int x) { GridViewTemplate template = new GridViewTemplate(); CreateTemplate(template); template.ShowChildViewCaptions = false; template.ShowColumnHeaders = false; template.ShowFilteringRow = false; parent.Templates.Add(template); GridViewRelation r = new GridViewRelation(parent, template); r.ChildColumnNames.Add("Children"); grid.Relations.Add(r); if (x < 10) { x++; CreateChildTemplate(template, x); } } private void UpdateTemplates(GridViewTemplate t) { t.Refresh(); foreach (GridViewTemplate g in t.Templates) { UpdateTemplates(g); } } #endregion Template #region Buttons private void buttonReload_Click(object sender, EventArgs e) { LoadData(); } private void buttonAddPeer_Click(object sender, EventArgs e) { if (grid.SelectedRows.Count == 1 && grid.SelectedRows[0].DataBoundItem != null && grid.SelectedRows[0].DataBoundItem is MyObject) { CreateChild((grid.SelectedRows[0].DataBoundItem as MyObject).Parent); } else { CreateChild(); } } private void buttonAddChild_Click(object sender, EventArgs e) { if (grid.SelectedRows.Count == 1 && grid.SelectedRows[0].DataBoundItem != null) { CreateChild(grid.SelectedRows[0].DataBoundItem as MyObject); } else { CreateChild(); } } private void buttonCollapse_Click(object sender, EventArgs e) { grid.MasterTemplate.CollapseAll(); } private void buttonExpand_Click(object sender, EventArgs e) { grid.MasterTemplate.ExpandAll(); } #endregion Buttons } public class MyObject { public MyObject Parent { get; set; } public string Name { get; set; } public bool Enabled { get; set; } public BindingList<MyObject> Children { get; set; } public MyObject(string name) { this.Enabled = true; this.Name = name; Children = new BindingList<MyObject>(); } public MyObject(string name, bool enabled) { this.Enabled = enabled; this.Name = name; Children = new BindingList<MyObject>(); } }}