This is a migrated thread and some comments may be shown as answers.

Hierarchy Child Template Column Width

4 Answers 399 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Randy
Top achievements
Rank 1
Randy asked on 09 Oct 2013, 01:39 PM
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>();
        }
    }
}

4 Answers, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 14 Oct 2013, 08:23 AM
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 >>
0
Randy
Top achievements
Rank 1
answered on 21 Oct 2013, 08:22 PM
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.
0
Randy
Top achievements
Rank 1
answered on 22 Oct 2013, 12:32 PM
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.
0
Accepted
Dess | Tech Support Engineer, Principal
Telerik team
answered on 24 Oct 2013, 03:11 PM
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 >>
Tags
GridView
Asked by
Randy
Top achievements
Rank 1
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Randy
Top achievements
Rank 1
Share this question
or