Hierarchy Child Template Column Width

5 posts, 1 answers
  1. Randy
    Randy avatar
    19 posts
    Member since:
    Oct 2012

    Posted 09 Oct 2013 Link to this post

    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?

    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>();
            }
        }
    }
  2. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3945 posts

    Posted 14 Oct 2013 Link to this post

    Hello Randy,

    Thank you for contacting Telerik Support.

    In order to achieve your goal, it is necessary to set Width, MaxWidth and MinWidth of the certain hierarchy level not in CellFormatting event, but in Form's constructor:
    public Form1()
    {
        InitializeComponent();
     
       //create relations and load data
     
        grid.MasterTemplate.Columns["Name"].Width = 150;
        grid.MasterTemplate.Columns["Name"].MaxWidth = 150;
        grid.MasterTemplate.Columns["Name"].MinWidth = 150;
     
        grid.Templates[0].Columns["Name"].Width = 131;
        grid.Templates[0].Columns["Name"].MaxWidth = 131;
        grid.Templates[0].Columns["Name"].MinWidth = 131;
     
        grid.Templates[0].Templates[0].Columns["Name"].Width = 131;
        grid.Templates[0].Templates[0].Columns["Name"].MaxWidth = 131;
        grid.Templates[0].Templates[0].Columns["Name"].MinWidth = 131;
     
        grid.MasterTemplate.ExpandAll();
    }

    I hope this information helps. Should you have further questions, I would be glad to help.

    Regards,
    Desislava
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINFORMS.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. Randy
    Randy avatar
    19 posts
    Member since:
    Oct 2012

    Posted 21 Oct 2013 Link to this post

    So that looks like it fixes the initial load if I set the first column width, min width, and max width when the template is created.

    I still am unable to have the child template columns line up when the user resizes the columns with the column headers.  I catch the column width changed event and set the child template column widths, but they still do not line up.  The more the user resizes the worse it seems to get.
  4. Randy
    Randy avatar
    19 posts
    Member since:
    Oct 2012

    Posted 22 Oct 2013 Link to this post

    I think I found part of it issue.  The master template does not seem to be reporting the correct column widths in the column resized event block.  So when I set the slate template column widths to be equal to the master template column widths the slave columns are a totally different size.

    The strange thing is that when I resize the second column the master column widths are incorrect.  However, when I resize the third column the master column widths are reported correctly and the grid resizes correctly.
  5. Answer
    Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3945 posts

    Posted 24 Oct 2013 Link to this post

    Hello Randy,

    Thank you for writing back,

    Please find attached the modified sample project which implements correct columns re-sizing of both templates. I have added ColumnWidthChanging event handler and Resize event handler to recalculate the columns width.

    I hope this information helps. Should you have further questions, I would be glad to help.

    Regards,
    Desislava
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WINFORMS.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
Back to Top