Declined
Last Updated: 05 Jun 2015 09:18 by ADMIN
ADMIN
Dess | Tech Support Engineer, Principal
Created on: 26 Feb 2015 15:36
Category: GridView
Type: Bug Report
1
FIX. RadGridView - when a custom GroupComparer is applied, groups of different levels are mixed-up
When you use a custom GroupComparer for the MasterTemplate, grouping is performed successfully for the first time. However, if you remove all groups and perform grouping again for the same columns, the grid behavior is not as expected: you will notice groups mismatching or duplication. Here is a sample code snippet which incorrect behavior is illustrated on the attached gif file:

public Form1()
{
    InitializeComponent();

    DataTable dt = new DataTable();
    dt.Columns.Add("Reference");
    dt.Columns.Add("Test Case");
    dt.Columns.Add("ChBW");
    dt.Columns.Add("Voltage");
    dt.Columns.Add("Environmental Conditions");
    dt.Columns.Add("RadioAccessTechnology");

    dt.Rows.Add("4.2.1", "E-Utran FDD...", "10", "C Nominal-2", "T Nominal - V Nominal", "E-UTRAN Only");
    dt.Rows.Add("5.2.1", "E-Utran FDD...", "3", "C Nominal-1", "T Nominal - V Nominal", "E-UTRAN Only");
    dt.Rows.Add("14.2.1", "E-Utran FDD...", "1", "C Nominal-3", "T Nominal - V Nominal", "E-UTRAN Only");
    dt.Rows.Add("2.2.1", "E-Utran FDD...", "4", "C Nominal-2", "T Nominal - V Nominal", "E-UTRAN Only");
    dt.Rows.Add("7.2.1", "E-Utran FDD...", "12", "C Nominal-1", "T Nominal - V Nominal", "E-UTRAN Only");
    dt.Rows.Add("2.2.1", "E-Utran FDD...", "2", "C Nominal-3", "T Nominal - V Nominal", "E-UTRAN Only");

    this.radGridControlSelection.DataSource = dt;
    this.radGridControlSelection.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;

    this.radGridControlSelection.MasterTemplate.GroupComparer = new GroupComparer();
}

public class GroupComparer : IComparer<Group<GridViewRowInfo>>
{
    public int Compare(Group<GridViewRowInfo> x, Group<GridViewRowInfo> y)
    {
        if (x.Level != y.Level)
        {
        }
        DataGroup group = x as DataGroup;

        var a = x.Header;
        var b = y.Header;

        int valueA;
        int valueB;

        if (group == null)
        {
            group = y as DataGroup;
        }
        if (group != null && group.GroupDescriptor != null && group.GroupDescriptor.GroupNames.Count > 0)
        {
            string propertyName = group.GroupDescriptor.GroupNames.First().PropertyName;
            if ((propertyName.ToUpper() == "VOLTAGE"))
            {
                int indexA = GetIndexContain(a.ToString().Split(new char[] { '-' })[1]);
                int indexB = GetIndexContain(b.ToString().Split(new char[] { '-' })[1]);

                if (indexA == indexB)
                {
                    return 0;
                }
                else if (indexA < indexB)
                {
                    return -1;
                }
                else
                {
                    return 1;
                }
            }
            else if (propertyName.ToUpper() == "RADIOACCESSTECHNOLOGY")
            {
                return x.Key.ToString().CompareTo(y.Key.ToString());
            }
            // BAND
            else if (propertyName.ToUpper() == "CHBW")
            {
                Int32.TryParse(a, out valueA);
                Int32.TryParse(b, out valueB);

                //ASCENDING SELECTED
                if (group.GroupDescriptor.GroupNames.First().Direction == ListSortDirection.Ascending)
                {
                    if (valueA > valueB)
                    {
                        return 1;
                    }
                    else if (valueA < valueB)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                }
                //DESCENDING
                else
                {
                    if (valueA > valueB)
                    {
                        return -1;
                    }
                    else if (valueA < valueB)
                    {
                        return 1;
                    }
                    else
                    {
                        return 0;
                    }
                }
            }
        }
        return x.Key.ToString().CompareTo(y.Key.ToString());
    }

    private int GetIndexContain(string a)
    {
        int parsedValue;
        if (int.TryParse(a, out parsedValue))
        {
            return 10 - parsedValue;
        }
        return -1;
    }
}


Workaround:

public class Grid:RadGridView
{
    public override string ThemeClassName  
    { 
        get 
        { 
            return typeof(RadGridView).FullName;  
        }
    }

    protected override RadGridViewElement CreateGridViewElement()
    {
        return new CustomGridViewElement();
    }
}

public class CustomGridViewElement : RadGridViewElement
{
    protected override Type ThemeEffectiveType     
    { 
        get    
        { 
            return typeof(RadGridViewElement);     
        }
    }

    protected override MasterGridViewTemplate CreateTemplate()
    {
        return new CustomMasterGridViewTemplate();
    }
}

public class CustomMasterGridViewTemplate : MasterGridViewTemplate
{
    protected override GridViewListSource CreateListSource()
    {
        return new CustomGridViewListSource(this);
    }
}

public class CustomGridViewListSource : GridViewListSource
{
    public CustomGridViewListSource(GridViewTemplate template) : base(template)
    {
    }

    protected override RadCollectionView<GridViewRowInfo> CreateDefaultCollectionView()
    {
        return new CustomGridDataView(this);
    }
}

public class CustomGridDataView : GridDataView
{
    public CustomGridDataView(GridViewListSource listSource) : base(listSource)
    {
    }

    protected override GroupBuilder<GridViewRowInfo> CreateGroupBuilder()
    {
        return new CustomGroupBuilder(this.Indexer);
    }
}

public class CustomGroupBuilder : GridGroupBuilder
{
    public CustomGroupBuilder(Index<GridViewRowInfo> index) : base(index)
    {
    }

    protected override Group<GridViewRowInfo> GetGroup(GroupCollection<GridViewRowInfo> cache,
        Group<GridViewRowInfo> newGroup, Group<GridViewRowInfo> parent, object key, int level)
    {
        GroupDescriptor currentDescriptor = this.CollectionView.GroupDescriptors[level];
        DataGroup group = (DataGroup)base.GetGroup(null, newGroup, parent, key, level);
        if (group.GroupDescriptor != null && group.GroupDescriptor != currentDescriptor)
        {
            SetGroupDescriptor(group, null);
            IGroupFactory<GridViewRowInfo> groupFactory = this.CollectionView.GroupFactory;
            group = (DataGroup)groupFactory.CreateGroup(key, parent);
            group.GroupBuilder = this;
        }
        SetGroupDescriptor(group, currentDescriptor);
        return group;
    }

    private void SetGroupDescriptor(DataGroup dataGroup, GroupDescriptor currentDescriptor)
    {
        FieldInfo fi = typeof(DataGroup).GetField("groupDescriptor", BindingFlags.NonPublic | BindingFlags.Instance);
        fi.SetValue(dataGroup, currentDescriptor);
    }
}
Attached Files:
1 comment
ADMIN
Ivan Todorov
Posted on: 05 Jun 2015 09:18
DECLINED: after further investigation it turns out that the custom comparer confuses the internal group caching algorithm of RadGridView. The line that causes this is:
        return x.Key.ToString().CompareTo(y.Key.ToString());
The keys are actually an object array so x.Key.ToString() returns "System.Object[]" and the line above will always return 0. To avoid this, use:
return ((object[])x.Key)[0].ToString().CompareTo(((object[])y.Key)[0].ToString());