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

Hiding tabs (children with no data) in ORM hierarchy

10 Answers 197 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Cat
Top achievements
Rank 1
Cat asked on 15 Feb 2011, 10:45 PM
I have a grid linked to sparse object data, and would like to hide any areas that don't have data from the user. In other words, I'm linked to objects that have child collections, and would like to hide the tabs for the rows that don't have any child data. I used the advice here to hide the expander when it's not needed, but all child tabs are still shown even if only one of them has child data. Is there a way to hide tabs that don't have child data?

10 Answers, 1 is accepted

Sort by
0
Richard Slade
Top achievements
Rank 2
answered on 15 Feb 2011, 11:02 PM
Hello Cat,

A quick scan of the forums reminded me of a similar question. Have a read of this forum post as I believe it deals with the issue you have here.
Regards,
Richard
0
Cat
Top achievements
Rank 1
answered on 16 Feb 2011, 03:56 AM
Upon further testing, it appears that the [+] is removed if (and only if) the first child collection is empty. I want this to be removed if *all* the child collections are empty, so the solution I linked to doesn't quite work for me. I've attached my code showing how this works/doesn't work. Here are my goals:

1) Show the [+] only if one or more of the child collections has data,
2) Then only show tabs for the child collections that do have data,
3) Finally (probably pipe dream here) be able to update the Caption property of the tab so that the tab also shows the number of rows it contains. E.g. - "Tab Title (3)", where the 3 refers to the number of rows in that tab.

Richard, I'd already seen the forum post you directed to me too, and it doesn't appear to work at all. All tabs appear regardless of whether they contain data or not. The user simply is unable to activate that tab, which is probably as misleading as being able to activate the tab and see garbage data.

I assume that this can probably be handled by catching the proper events, but I seem to be failing in that department. Any help would be greatly appreciated!!

Below is the code I'm testing with.

Form1.cs
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Telerik.WinControls.UI;
  
namespace RadGridViewExample
{
    public partial class Form1 : Form
    {
          
        public Form1()
        {
            InitializeComponent();
  
            gvGridView = CreateGridViewFromSearch(gvGridView);
        }
  
        private RadGridView CreateGridViewFromSearch(RadGridView gvResults)
        {
            gvResults.Dock = DockStyle.Fill;
            gvResults.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.None;
            gvResults.ReadOnly = true;
            gvResults.Text = "Test of Hierarchial Data in Grid";
  
            gvResults.ViewCellFormatting += radGridView1_ViewCellFormatting;
            gvResults.ChildViewExpanding += radGridView1_ChildViewExpanding;
              
            DataBlob resultsBlob = TestData.GetTestData();
  
  
            // Set up the master template
            gvResults.MasterTemplate.AllowAddNewRow = false;
            gvResults.MasterTemplate.AutoGenerateColumns = false;
            gvResults.MasterTemplate.Tag = TestData.MainCollectionName;
            gvResults.DataSource = resultsBlob.Data;
            gvResults.TableElement.BeginUpdate();
            gvResults.MasterTemplate.Columns.Clear();
              
            // First do the main level
            NameAliasSet mainAliasSet = resultsBlob.AliasDictionaries.Where(x => x.CollectionName == TestData.MainCollectionName).FirstOrDefault();
            NameAliasSet columnAliasSet = resultsBlob.AliasDictionaries.Where(x => x.CollectionName == TestData.CollectionAliasCollectionName).FirstOrDefault();
            NameAliasSet childParentSet = resultsBlob.AliasDictionaries.Where(x => x.CollectionName == TestData.ChildParentCollectionName).FirstOrDefault();
  
            // Create columns from alias collection
            foreach (var record in mainAliasSet.ColumnAliases)
            {
                GridViewTextBoxColumn column = new GridViewTextBoxColumn();
                column.Name = record.Key;
                column.HeaderText = record.Value;
                column.FieldName = record.Key;
                column.MinWidth = 50;
                column.MaxWidth = 250;
                column.AutoSizeMode = BestFitColumnMode.DisplayedDataCells;
  
                gvResults.MasterTemplate.Columns.Add(column);
            }
  
            // Now do the child sets
            foreach (NameAliasSet aliasSet in resultsBlob.AliasDictionaries.Where(x => IsNotACollection(x.CollectionName)))
            {
                string name = aliasSet.CollectionName;
                Dictionary<string, string> dictionary = aliasSet.ColumnAliases;
  
                GridViewTemplate template = new GridViewTemplate();
                GridViewTemplate parentTemplate = GetParentTemplateByName(name, gvResults, childParentSet);
  
                parentTemplate.Templates.Add(template);
  
                template.Tag = name;
                template.Caption = columnAliasSet.ColumnAliases[name];
  
                // Create columns from alias collection
                foreach (var record in dictionary)
                {
                    GridViewTextBoxColumn column = new GridViewTextBoxColumn();
                    column.Name = record.Key;
                    column.HeaderText = record.Value;
                    column.FieldName = record.Key;
                    column.MinWidth = 50;
                    column.MaxWidth = 250;
                    column.AutoSizeMode = BestFitColumnMode.DisplayedDataCells;
  
                    template.Columns.Add(column);
                }
                template.BestFitColumns();
  
                GridViewRelation relation = new GridViewRelation(parentTemplate, template);
                relation.RelationName = name + "Relation";
                relation.ChildColumnNames.Add(name);
                gvResults.Relations.Add(relation);
            }
  
            gvResults.TableElement.EndUpdate(false);
  
            gvResults.MasterTemplate.BestFitColumns();
  
            return gvResults;
        }
  
        private bool IsExpandable(GridViewRowInfo rowInfo)
        {
            if (rowInfo.ChildRows != null && rowInfo.ChildRows.Count > 0)
            {
                return true;
            }
  
            return false;
        }
  
        private void radGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e)
        {
            GridGroupExpanderCellElement cell = e.CellElement as GridGroupExpanderCellElement;
            if (cell != null && e.CellElement.RowElement is GridDataRowElement)
            {
                if (!IsExpandable(cell.RowInfo))
                {
                    cell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
                }
                else
                {
                    cell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Visible;
                }
            }
        }
  
        private void radGridView1_ChildViewExpanding(object sender, ChildViewExpandingEventArgs e)
        {
            e.Cancel = !IsExpandable(e.ParentRow);
        }
  
        private GridViewTemplate GetParentTemplateByName(string name, RadGridView gvResults, NameAliasSet childParentSet)
        {
            string parentName = childParentSet.ColumnAliases[name];
  
            GridViewTemplate template = GetTemplateByNameRecursive(parentName, gvResults.MasterTemplate);
  
            return template ?? gvResults.MasterTemplate;
        }
  
        private static GridViewTemplate GetTemplateByNameRecursive(string name, GridViewTemplate template)
        {
            if (template.Tag.ToString() == name)
                return template;
  
            if (template.Templates.Count > 0)
            {
                foreach (GridViewTemplate viewTemplate in template.Templates)
                {
                    GridViewTemplate result = GetTemplateByNameRecursive(name, viewTemplate);
                    if (result != null)
                        return result;
                }
            }
            return null;
        }
  
        private static bool IsNotACollection(string collection)
        {
            return collection != TestData.MainCollectionName &&
                   collection != TestData.CollectionAliasCollectionName &&
                   collection != TestData.ChildParentCollectionName;
        }
    }
}

TestData.cs (using NBuilder)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using FizzWare.NBuilder;
  
namespace RadGridViewExample
{
    public class MainDataClass
    {
        public string Name { get; set; }
        public string Country { get; set; }
        public string Remarks { get; set; }
        public string Comments { get; set; }
        public string Title { get; set; }
        [Browsable(false)] public string Id { get; set; }
        [Browsable(false)] public decimal X { get; set; }
        [Browsable(false)] public decimal Y { get; set; }
        public List<BuildingClass> BuildingCollection { get; set; }
        public List<SpaceshipClass> ShipCollection { get; set; }
    }
  
    public static class TestData
    {
        public static readonly string MainCollectionName = "Main";
        public static readonly string ChildParentCollectionName = "ParentChildCollection";
        public static readonly string CollectionAliasCollectionName = "CollectionAliasCollection";
  
        public static DataBlob GetTestData()
        {
            DataBlob result = new DataBlob();
  
            result.Data = GenerateMainResultList(10);
  
            result.AliasDictionaries = new List<NameAliasSet>();
            result.AliasDictionaries.Add(new NameAliasSet() { CollectionName = "Main", ColumnAliases = GetMainDictionary()});
            result.AliasDictionaries.Add(new NameAliasSet() { CollectionName = "BuildingCollection", ColumnAliases = GetSub1Dictionary() });
            result.AliasDictionaries.Add(new NameAliasSet() { CollectionName = "ShipCollection", ColumnAliases = GetSub2Dictionary() });
            result.AliasDictionaries.Add(new NameAliasSet() { CollectionName = "TrainCollection", ColumnAliases = GetSubSubDictionary() });
            result.AliasDictionaries.Add(new NameAliasSet() { CollectionName = "ParentChildCollection", ColumnAliases = GetChildParentDictionary() });
            result.AliasDictionaries.Add(new NameAliasSet() { CollectionName = "CollectionAliasCollection", ColumnAliases = GetCollectionAliasDictionary() });
  
            return result;
        }
  
        public static List<MainDataClass> GenerateMainResultList(int size)
        {
            var rand = new RandomGenerator();
            var test = rand.Next(0, 6);
  
            return Builder<MainDataClass>.CreateListOfSize(size)
                .WhereTheFirst(3)
                    .Have(x => x.BuildingCollection = new List<BuildingClass>())
                    .Have(x => x.ShipCollection = new List<SpaceshipClass>())
                .AndTheNext(2)
                    .Have(x => x.BuildingCollection = new List<BuildingClass>())
                    .Have(x => x.ShipCollection = GenerateSpaceshipList(3))
                .AndTheNext(2)
                    .Have(x => x.BuildingCollection = GenerateBuildingList(3))
                    .Have(x => x.ShipCollection = new List<SpaceshipClass>())
                .AndTheNext(3)
                    .Have(x => x.BuildingCollection = GenerateBuildingList(3))
                    .Have(x => x.ShipCollection = GenerateSpaceshipList(3))
                .Build().ToList();
        }
  
        public static List<BuildingClass> GenerateBuildingList(int size)
        {
            if (size == 0)
                return new List<BuildingClass>();
  
            return Builder<BuildingClass>.CreateListOfSize(size)
                .WhereAll()
                .WhereRandom(1)
                    .Have(x => x.BuildingName = "Yea! Building!")
                .Build().ToList();
        }
  
        public static List<SpaceshipClass> GenerateSpaceshipList(int size)
        {
            if (size == 0)
                return new List<SpaceshipClass>();
  
            return Builder<SpaceshipClass>.CreateListOfSize(size)
                .WhereAll()
                    .Have(x => x.TrainCollection = GenerateTrainList(5))
                .WhereRandom(1)
                    .Have(x => x.StarshipType = "Yea! Spaceship!")
                .Build().ToList();
        }
  
        public static List<TrainClass> GenerateTrainList(int size)
        {
            if (size == 0)
                return new List<TrainClass>();
  
            return Builder<TrainClass>.CreateListOfSize(size)
                .WhereRandom(1)
                    .Have(x => x.TrainType = "Yea! Train!")
                .Build().ToList();
        }
  
        public static Dictionary<string, string> GetMainDictionary()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("Name", "Name");
            dictionary.Add("Country", "Country");
            dictionary.Add("Remarks", "Remarks");
            dictionary.Add("Comments", "Comments");
            dictionary.Add("Title", "Title");
  
            return dictionary;
        }
  
        public static Dictionary<string, string> GetSub1Dictionary()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("BuildingName", "Building Name");
            dictionary.Add("Purpose", "Purpose");
  
            return dictionary;
        }
  
        public static Dictionary<string, string> GetSub2Dictionary()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("StarshipType", "Starship Type");
            dictionary.Add("Engine", "Engine");
  
            return dictionary;
        }
  
        public static Dictionary<string, string> GetSubSubDictionary()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("TrainType", "Train Type");
            dictionary.Add("Name", "Name");
  
            return dictionary;
        }
  
        public static Dictionary<string, string> GetChildParentDictionary()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("BuildingCollection", "Main");
            dictionary.Add("ShipCollection", "Main");
            dictionary.Add("TrainCollection", "ShipCollection");
  
            return dictionary;
        }
  
        public static Dictionary<string, string> GetCollectionAliasDictionary()
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add("BuildingCollection", "Buildings");
            dictionary.Add("ShipCollection", "Ships");
            dictionary.Add("TrainCollection", "Trains");
  
            return dictionary;
        }
    }
  
    public class BuildingClass
    {
        public string BuildingName { get; set; }
        public string Purpose { get; set; }
    }
  
    public class SpaceshipClass
    {
        public string StarshipType { get; set; }
        public string Engine { get; set; }
        public List<TrainClass> TrainCollection { get; set; }
    }
  
    public class TrainClass
    {
        public string TrainType { get; set; }
        public string Name { get; set; }
    }
  
    public class DataBlob
    {
        public List<MainDataClass> Data { get; set; }
        public List<NameAliasSet> AliasDictionaries { get; set; }
    }
  
    public class NameAliasSet
    {
        public string CollectionName { get; set; }
        public Dictionary<string, string> ColumnAliases { get; set; }
    }
  
}
0
Cat
Top achievements
Rank 1
answered on 16 Feb 2011, 06:23 PM
I was able to get 1) "Show the [+] only if one or more of the child collections has data," working by modifying the IsExpandable method, as seen below. This checks all child collections, not just the first. Still need help with 2 & 3 though!

private bool IsExpandable(GridViewRowInfo rowInfo)
        {
            GridViewHierarchyRowInfo hRowInfo = rowInfo as GridViewHierarchyRowInfo;
            if (hRowInfo == null) return false;
  
            if (hRowInfo.ChildRow != null && hRowInfo.ChildRow.ChildViewInfos.Count > 0)
            {
                int count = 0;
                return hRowInfo.ChildRow.ChildViewInfos.Any(info => info.ChildRows.Count > 0);
            }
  
            return false;
        }

0
Richard Slade
Top achievements
Rank 2
answered on 16 Feb 2011, 06:43 PM
Hi Cat,

I'm glad you've found a solution for the first part, regarding #3 - the tab row count. I haven't had chance to try this in a full version yet, but could you put the following into your code and give it a go. It assumes that there is a Master Template, and then two equal child templates below that.

void radGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e)
{
    if (e.CellElement is GridDetailViewCellElement && e.CellElement.Children.Count != 0)
    {
        var pageView = e.CellElement.Children[0] as RadPageViewStripElement;
        if (pageView == null)
        {
            return;
        }
        pageView.Items[0].Text = "Something " + e.CellElement.RowInfo.Parent.ChildRows.Count.ToString();
        pageView.Items[1].Text = "Something else " + ((GridViewTemplate)e.CellElement.RowInfo.Parent).Templates[0].ChildRows.Count.ToString();
    }
}

Richard
0
Cat
Top achievements
Rank 1
answered on 16 Feb 2011, 08:45 PM
Hi Richard,

Thanks for the reply. I tried your code, but unfortunately it's still not quite right. The first line:

pageView.Items[0].Text = "Something " + e.CellElement.RowInfo.Parent.ChildRows.Count.ToString();

only returns the number of rows of the parent set, and the second line:

pageView.Items[1].Text = "Something else " + ((GridViewTemplate)e.CellElement.RowInfo.Parent).Templates[0].ChildRows.Count.ToString(); 

appears to only return zero, apparently because the templates (other than the master template) don't have the row counts. I think this is because I'm using an object collection as the datasource.
0
Richard Slade
Top achievements
Rank 2
answered on 16 Feb 2011, 08:48 PM
Hi.

Yes, I've since realised this and I'm going to try and put together a sample and see if I can get it to work the way that you need.
I'll get back to you as soon as I can.
regards
Richard
0
Accepted
Richard Slade
Top achievements
Rank 2
answered on 16 Feb 2011, 09:18 PM
Hi again Cat,

Whilst I ewas preparing this, I had a look in the PITS system (public issue tracking system) for a bug that I think is in the hierarcy grid, but came upon this issue to be fixed (Issue ID 4717 - FIX When you delete all rows of a child view in tabbed hierarchy, the tab item should become invisible.), which means it's good news as Telerik are already aware of this and are going to be making this a feature in one of the upcoming releases. You can click on the link given to vote for the issue which helps raise it's priority.

More to follow
Richard
0
Cat
Top achievements
Rank 1
answered on 16 Feb 2011, 09:45 PM
Thanks Richard!

I guess this means there isn't a workaround available yet? Well, at least I know not to spend much more time working on this. I'm going to consider this thread closed as it appears to be a design oversight. <sigh> I'll still keep a watch on this thread if you come up with more ideas though.

Again, thank you for your help Richard!
0
Richard Slade
Top achievements
Rank 2
answered on 16 Feb 2011, 10:09 PM
No problem. i'll spend some time on it inbetween others to see if I can get something that's useful to you.
Regards,
Richard
0
Jack
Telerik team
answered on 18 Feb 2011, 08:47 AM
Hello Cat,

The following code should do the job:

void
radGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e)
{
    GridDetailViewCellElement cell = e.CellElement as GridDetailViewCellElement;
    if (cell != null)
    {
        GridViewHierarchyRowInfo hierarchyRow = (GridViewHierarchyRowInfo)((GridViewDetailsRowInfo)cell.RowInfo).Owner;
        for (int i = 0; i < cell.PageViewElement.Items.Count; i++)
        {
            RadPageViewItem item = cell.PageViewElement.Items[i];
            GridViewInfo viewInfo = hierarchyRow.Views[i];
            item.Text = viewInfo.ViewTemplate.Caption + viewInfo.ChildRows.Count;
        }
    }
}

Best wishes,
Jack
the Telerik team
Tags
GridView
Asked by
Cat
Top achievements
Rank 1
Answers by
Richard Slade
Top achievements
Rank 2
Cat
Top achievements
Rank 1
Jack
Telerik team
Share this question
or