Enable Sorting for a GridViewDataColumn with a custom FilteringControl

0 Answers 129 Views
GridView
Martin
Top achievements
Rank 2
Iron
Iron
Iron
Martin asked on 05 May 2022, 07:51 AM

I have a GridViewDataColumn that binds to a complex model (Custom class with a few properties and a ToString method)

The GridViewDataColumn also has a CustomGridFilter which is able to filter the column and has it's own popup. 

But .. now the users also want to Order by this column - but nothing happens when clicking on the Column Header. 

What am i missing ?

<telerik:GridViewDataColumn Width="100"
		DataMemberBinding="{Binding YearRange}"
		Header="Ã…rgang">
	<telerik:GridViewDataColumn.FilteringControl>
		<local:CustomGridFilter Aargang="{Binding ElementName=root, Path=VintageYear, Mode=TwoWay}" />
	</telerik:GridViewDataColumn.FilteringControl>
</telerik:GridViewDataColumn>
public class YearRange : IEquatable<int>
{
    public int FromYear { get; set; }

    public int ToYear { get; set; }

    public int Year { get; set; }

    public override string ToString()
    {
        if (FromYear == ToYear)
            return FromYear.ToString();

        return FromYear + "-" + ToYear;
    }

  #region Equals, GetHashCode

  #region Comparison operators override
}

public partial class CustomGridFilter : UserControl, IFilteringControl, INotifyPropertyChanged
{
    private GridViewBoundColumnBase column;
    private CompositeFilterDescriptor compositeFilter;
    private FilterDescriptor rangeFilter;

    #region INotifyPropertyChanged

    public void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    #region IsActive DependencyProperty 
    public bool IsActive
    {
        get { return (bool)GetValue(IsActiveProperty); }
        set { SetValue(IsActiveProperty, value); }
    }

    public static readonly DependencyProperty IsActiveProperty =
        DependencyProperty.Register(
            "IsActive",
            typeof(bool),
            typeof(CustomGridFilter),
            new PropertyMetadata(false));
    #endregion

    #region Aargang DependencyProperty 

    public int? Aargang
    {
        get { return (int?)GetValue(AargangProperty); }
        set { SetValue(AargangProperty, value); }
    }

    public static readonly DependencyProperty AargangProperty =
        DependencyProperty.Register(
            "Aargang",
            typeof(int?),
            typeof(CustomGridFilter),
            new PropertyMetadata(
                null,
                (sender, evt) => { ((CustomGridFilter)sender).OnPropertyChanged("Aargang"); }
            )
        );

    #endregion

    public CustomGridFilter()
    {
        InitializeComponent();

        DataContext = this;

        PropertyChanged += CustomGridFilter_PropertyChanged;
    }

    private void CustomGridFilter_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Aargang" && Aargang>1900 && Aargang<2100)
        {
            OnFilter(null, null);
        }
    }

    public void Prepare(Telerik.Windows.Controls.GridViewColumn column)
    {
        this.column = column as GridViewBoundColumnBase;

        if (this.column == null)
        {
            return;
        }

        if (compositeFilter == null)
        {
            CreateFilters();
        }
    }

    private void CreateFilters()
    {
        string dataMember = column.DataMemberBinding.Path.Path;

        compositeFilter = new CompositeFilterDescriptor();

        rangeFilter = new FilterDescriptor(dataMember, FilterOperator.IsEqualTo, null);

        compositeFilter.FilterDescriptors.Add(rangeFilter);
    }

    private void OnFilter(object sender, RoutedEventArgs e)
    {
        rangeFilter.Value = new YearRange { Year = Aargang ?? 0 };

        if (!column.DataControl.FilterDescriptors.Contains(compositeFilter))
        {
            column.DataControl.FilterDescriptors.Add(compositeFilter);
        }

        IsActive = true;

        var popup = this.ParentOfType<System.Windows.Controls.Primitives.Popup>();
        if (popup != null)
        {
            popup.IsOpen = false;
        }
    }

    private void OnClear(object sender, RoutedEventArgs e)
    {
        if (column.DataControl.FilterDescriptors.Contains(compositeFilter))
        {
            column.DataControl.FilterDescriptors.Remove(compositeFilter);
        }

        Aargang = 0;

        IsActive = false;

        var popup = this.ParentOfType<System.Windows.Controls.Primitives.Popup>();
        if (popup != null)
        {
            popup.IsOpen = false;
        }
    }

}

 

 

 

Dilyan Traykov
Telerik team
commented on 09 May 2022, 09:46 AM

Hello Martin,

Thank you for the provided code snippets.

I tried replicating the issue you described and indeed, for the sorting to work as expected, you need to implement the IComparable interface on the YearRange class so that the RadGridView control understands how the sorting should be performed. For example:
        public int CompareTo(YearRange other)
        {
            return this.Year.CompareTo(other.Year);
        }
Alternatively, you can use one of the other custom sorting mechanisms described here: Custom Sorting. Please let me know if any of them works for you.
Martin
Top achievements
Rank 2
Iron
Iron
Iron
commented on 09 May 2022, 11:02 AM | edited

Hi Dilyan, thanks for the hints.

It worked in 1 out of 2 GridViews .. 

but on the 2nd im getting this error :

Working:
- ItemsSource bound directly to collection (ObservableCollection)

Not Working
- ItemsSource bound to CollectionViewSource 

Dilyan Traykov
Telerik team
commented on 10 May 2022, 01:06 PM

Hi Martin,

Thank you for the provided stack trace.

Would you, however, be able to demonstrate the exception in a small sample project so that I can further investigate its cause as I am currently unable to replicate the same exception at my end?

Thank you in advance for your cooperation on the matter.

Martin
Top achievements
Rank 2
Iron
Iron
Iron
commented on 11 May 2022, 01:02 PM

I've managed to create a sample solution that shows the error. 

it seems that the error truly stems from the CollectionViewSouce... 

Dilyan Traykov
Telerik team
commented on 13 May 2022, 12:49 PM

Hello Martin,

Thank you very much for the provided project. I can confirm that I was able to replicate the issue at my end.

Indeed, this seems to stem from the use of a CollectionViewSouce. With this said, would you find it possible to use the QueryableCollectionViewSource class instead?

I've updated the project you provided to demonstrate how you can use the QueryableCollectionViewSource. Please have a look and let me know if the same would be applicable in your original application.

No answers yet. Maybe you can help?

Tags
GridView
Asked by
Martin
Top achievements
Rank 2
Iron
Iron
Iron
Share this question
or