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>();
}
}
}