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

Custom Sort Children

2 Answers 185 Views
TreeListView
This is a migrated thread and some comments may be shown as answers.
Omar
Top achievements
Rank 1
Omar asked on 21 Oct 2019, 08:21 PM

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

2 Answers, 1 is accepted

Sort by
0
Martin Ivanov
Telerik team
answered on 24 Oct 2019, 11:40 AM

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?

Regards,
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.
0
Omar
Top achievements
Rank 1
answered on 28 Oct 2019, 08:07 PM

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.

XAML:
<telerik:RadTreeListView Grid.Row="2" x:Name="DeckDataGrid"
                               EnableLostFocusSelectedState="False"
                               SelectionMode="Single"
                               CanUserSortColumns="True"
                               AutoGenerateColumns="False"
                               behaviors:ListTreeSortBehavior.AllowCustomSort="True"
                               ItemsSource="{Binding Source={StaticResource EngineeringDeckMarksView}}"
                               TreeLinesVisibility="Hidden"
                               SelectedItem="{Binding SelectedDeckMark, Mode=TwoWay}"
                               HierarchyColumnIndex="1">
        <telerik:RadTreeListView.ChildTableDefinitions >
          <telerik:TreeListViewTableDefinition ItemsSource="{Binding ChildrenDeckMarks}" />
        </telerik:RadTreeListView.ChildTableDefinitions>
        <telerik:RadTreeListView.Columns>
          <telerik:GridViewDataColumn MinWidth="32" MaxWidth="100" IsSortable="False" EditTriggers="None">
            <telerik:GridViewDataColumn.CellTemplate>
              <DataTemplate DataType="deck:IBaseDeckMarkViewModel">
                <CheckBox Margin="10 0 0 0"
                          CommandParameter="{Binding}"
                          IsChecked="{Binding IsSelected, Mode=TwoWay}" />
              </DataTemplate>
            </telerik:GridViewDataColumn.CellTemplate>
          </telerik:GridViewDataColumn>
          <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" />
        </telerik:RadTreeListView.Columns>
      </telerik:RadTreeListView>
    </Grid>

--------------------------------------------
DEPENDENCY PROPERTY:
public static readonly DependencyProperty AllowCustomSortProperty
            = DependencyProperty.RegisterAttached(
                "AllowCustomSort",
                typeof(bool),
                typeof(ListTreeSortBehavior),
                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;
        }

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

private static void OnDataGridSort(object sender, GridViewSortingEventArgs e)
        {
            if (!(sender is RadTreeListView grid) || !GetAllowCustomSort(grid))
                return;
            if (!(grid.ItemsSource is ListCollectionView list))
                return;
            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;
            }
            else
            {
                var property = e.Column.SortMemberPath ?? (e.Column as GridViewDataColumn).GetDataMemberName();
                var comparer = new DefaultGridComparer(
                    property,
                    sortDirection,
                    secondaryComparer
                    );
                list.CustomSort = comparer;
            }
        }

--------------------------------------
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;
            }
        }

Tags
TreeListView
Asked by
Omar
Top achievements
Rank 1
Answers by
Martin Ivanov
Telerik team
Omar
Top achievements
Rank 1
Share this question
or