Search code examples
c#wpfdatagridobservablecollectioncollectionviewsource

WPF Observable collection & Collection View Source applying sort on filtered items


WPF Filtering and Sorting on Observable Collection

What I have?

I have a usercontrol with a Datagrid and a textbox for searching the datagrid. In my viewmodel I have an ObservableCollection called EmployeeCollection which is bound to the datagrid. Let us consider the following is the content of the Employee Collection

EmployeeName email id

Emp1 xyz1@abc.com

Emp xyz@abc.com

Emp 2 xyz2@abc.com

ABC abc@abc.com

DEF def@abc.com

This collection is bound to the datagrid and everything is displayed properly. And in the view model I have added the following filter to the collections default view for searching the collection using the input provided in textbox. To display the exact match as well as the other entries starting with the given search text.

CollectionViewSource.GetDefaultView(EmployeeCollection).Filter =
                        x => (((EmployeeViewModel)x).Name.Equals(SearchText, StringComparison.CurrentCultureIgnoreCase) || ((EmployeeViewModel)x).Name.ToLower().StartsWith(SearchText.ToLower()));

What I Expect?

Now with the Search Text box I am typing “Emp” and click on the search results. The result which I am expect is to display the exact match first and then display the partial match(starts with data) as follows.

Emp xyz@abc.com

Emp1 xyz1@abc.com

Emp 2 xyz2@abc.com

However I am not getting it in the expected order. I am getting the result in the order in which data is stored in the EmployeeCollection.

Emp1 xyz1@abc.com

Emp xyz@abc.com

Emp 2 xyz2@abc.com

Now How do I achieve the sorting with exact match first and then partial match?


Solution

  • You can use CustomSort along with your Filter to sort CollectionView accordingly

    public class EmployeeComparer : IComparer
    {
        public int Compare(object x, object y)
        {
            return string.Compare((EmployeeViewModel)x.Name, (EmployeeViewModel)y.Name);
        }
    }
    
    
    
    
    var view = (ListCollectionView)CollectionViewSource.GetDefaultView(EmployeeCollection);
     view.CustomSort = new EmployeeComparer();