Custom Sort Children

3 posts, 0 answers
  1. Omar
    Omar avatar
    5 posts
    Member since:
    Jan 2013

    Posted 21 Oct 2019 Link to this post

    Is possible add a custom sort for children? Or sort just parents?

  2. Martin Ivanov
    Martin Ivanov avatar
    2298 posts

    Posted 24 Oct 2019 Link to this post

    Hello Omar,

    Currently, the same sorting is applied to all levels of the tree list. There is no API to easily add a custom sorting to the separate levels. However, I have logged a feature request to introduce such. I also updated your Telerik points.

    In the meantime, you can manually sort the items collection (assigned to the ItemsSource of the control) that holds the data. To do this, you can use the Sorting event of RadTreeListView (deriving from RadGridView). Can you try this and let me know if it helps?

    Martin Ivanov
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. Omar
    Omar avatar
    5 posts
    Member since:
    Jan 2013

    Posted 28 Oct 2019 in reply to Martin Ivanov Link to this post

    I tried adding a Dependency Property and Adding a custom sort by IComparable it use the compare in all the columns but those columns that are not a complex object, for example strings and integers are sorted by those types instead of the custom compare. 
    I can see through a break point that it consume the custom compare but the sort is by alphabetic instead of the sort. 
    Comparer will return always zero so it should keep the same sequence. If you see Designation column is string type and is sort by alphabetic instead of the comparer result including parents and children.

    <telerik:RadTreeListView Grid.Row="2" x:Name="DeckDataGrid"
                                   ItemsSource="{Binding Source={StaticResource EngineeringDeckMarksView}}"
                                   SelectedItem="{Binding SelectedDeckMark, Mode=TwoWay}"
            <telerik:RadTreeListView.ChildTableDefinitions >
              <telerik:TreeListViewTableDefinition ItemsSource="{Binding ChildrenDeckMarks}" />
              <telerik:GridViewDataColumn MinWidth="32" MaxWidth="100" IsSortable="False" EditTriggers="None">
                  <DataTemplate DataType="deck:IBaseDeckMarkViewModel">
                    <CheckBox Margin="10 0 0 0"
                              IsChecked="{Binding IsSelected, Mode=TwoWay}" />
              <telerik:GridViewDataColumn Header="Mark" DataMemberBinding="{Binding MarkNumber}" SortingState="Ascending" MinWidth="100"  Width="120" IsReadOnly="True" SortMemberPath="DeckLevel"  IsCustomSortingEnabled="true"/>
              <telerik:GridViewDataColumn Header="Qty" SortingState="Ascending" DataMemberBinding="{Binding Quantity, TargetNullValue='--', FallbackValue='--' }" MinWidth="71" Width="71" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Avail&#x0a;Qty" SortingState="Ascending" DataMemberBinding="{Binding AvailableQuantity, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="80" Width="100" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Length" SortingState="Ascending" DataMemberBinding="{Binding Length, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}', Converter={StaticResource LengthDisplayConverter}, ConverterParameter=FractionalFeet8th}" MinWidth="90" Width="90" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Designation" SortingState="Descending" IsSortable="True" DataMemberBinding="{Binding Designation, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="140" Width="150" IsReadOnly="True"  IsCustomSortingEnabled="True" />
              <telerik:GridViewDataColumn Header="Gage" SortingState="Descending" DataMemberBinding="{Binding Gage, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="70" Width="70" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Galv" SortingState="Ascending" SortMemberPath="GalvanizationThickness" DataMemberBinding="{Binding Galvanization, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}'}" MinWidth="70" Width="70" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Top&#x0a;Finish" SortingState="Ascending" DataMemberBinding="{Binding TopFinish, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="90" Width="90" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Bot&#x0a;Finish" SortingState="Ascending" DataMemberBinding="{Binding BottomFinish, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="90" Width="90" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Emboss" SortingState="Ascending" DataMemberBinding="{Binding Emboss, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}'}" MinWidth="110" Width="110" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Acoustic" SortingState="Ascending" DataMemberBinding="{Binding Acoustic, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="110" Width="110" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Perf" SortingState="Ascending" DataMemberBinding="{Binding Perforation, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="80" Width="120" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Yield" SortingState="Ascending" DataMemberBinding="{Binding Yield, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="80" Width="120" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Wt Ea" SortingState="Ascending" DataMemberBinding="{Binding WeightEach, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}', Converter={StaticResource RoundAwayFromZeroConverter}, ConverterParameter=2}" MinWidth="80" Width="120" IsReadOnly="True" />
              <telerik:GridViewDataColumn Header="Width" SortingState="Ascending" DataMemberBinding="{Binding Width, TargetNullValue='--', FallbackValue='--', StringFormat='{}{0}' }" MinWidth="105" Width="*" IsReadOnly="True" />

    public static readonly DependencyProperty AllowCustomSortProperty
                = DependencyProperty.RegisterAttached(
                    new PropertyMetadata(false, OnAllowCustomSortChanged));
            /// <summary>Sets the allow custom sort property.</summary>
            /// <param name="element">The element.</param>
            /// <param name="value">if set to <c>true</c> enable the custom sorter.</param>
            public static void SetAllowCustomSort(DependencyObject element, bool value)
                element.SetValue(AllowCustomSortProperty, value);

            public static bool GetAllowCustomSort(DependencyObject element)
                var allowCustomSort = element.GetValue(AllowCustomSortProperty);
                return allowCustomSort != null && (bool)allowCustomSort;

     private static void OnAllowCustomSortChanged(
                DependencyObject d,
                DependencyPropertyChangedEventArgs e)
                if (!(d is RadTreeListView grid))
                if (e.NewValue as bool? ?? false)
                    grid.Sorting += OnDataGridSort;
                    grid.Sorting -= OnDataGridSort;

    private static void OnDataGridSort(object sender, GridViewSortingEventArgs e)
                if (!(sender is RadTreeListView grid) || !GetAllowCustomSort(grid))
                if (!(grid.ItemsSource is ListCollectionView list))
                e.Handled = true;

                if (e.OldSortingState == SortingState.Descending)
                    e.NewSortingState = SortingState.Ascending;
                var sortDirection = e.NewSortingState;
                var secondaryComparer = GetSecondarySortComparer(grid)
                                     ?? new DefaultGridComparer(GetSecondarySortColumn(grid), SortingState.Ascending);
                secondaryComparer.SortDirection = SortingState.Ascending;
                var jComparer = GetColumnComparer(e.Column);
                if (jComparer != null)
                    if (secondaryComparer != jComparer)
                        jComparer.SecondaryComparer = secondaryComparer;
                    jComparer.SortDirection = sortDirection;
                    list.CustomSort = jComparer;
                    var property = e.Column.SortMemberPath ?? (e.Column as GridViewDataColumn).GetDataMemberName();
                    var comparer = new DefaultGridComparer(
                    list.CustomSort = comparer;

    private class DefaultGridComparer : ITreeListComparer
                private readonly string _propertyName;
                public DefaultGridComparer(
                    string propertyName,
                    SortingState sortDirection,
                    ITreeListComparer secondaryComparer = null)
                    SortDirection = sortDirection;
                    SecondaryComparer = secondaryComparer;
                    _propertyName = propertyName;
                public ITreeListComparer SecondaryComparer { get; set; }
                public SortingState SortDirection { get; set; }
                public int Compare(object x, object y)
                    if (string.IsNullOrEmpty(_propertyName))
                        return 0;
                    var typeX = x?.GetType();
                    var propertyX = typeX?.GetProperty(_propertyName);
                    if (propertyX == null)
                        return 0;
                    var typeY = y?.GetType();
                    var propertyY = typeY?.GetProperty(_propertyName);
                    if (propertyY == null)
                        return 0;
                    var first = propertyX.GetValue(x) as IComparable;
                    var second = propertyY.GetValue(y) as IComparable;
                    if (first == null || second == null || first is string)
                        return -1;
                    var deckLevel = typeX?.GetProperty("DeckLevel");
                    var deckLevelValue = deckLevel?.GetValue(x) as DeckLevel;
                    if (deckLevelValue == null || !deckLevelValue.IsParent)
                        return 0;
                    var result = first.CompareTo(second);
                    if (result == 0 && SecondaryComparer != null)
                        result = SecondaryComparer.Compare(x, y);
                    result = SortDirection == SortingState.Ascending ? result : -result;
                    return result;

Back to Top