Search code examples
wpffilterlistboxexpander

How to apply filter when binding with collection inside collection in wpf using collection view source


I have a ListBox having different expander as ListBoxItem. expander has ListBox in its content. Now I wanted to apply search filter on header and also in the Content of expander.

For example:-

if header has a and content has b,c,d,bt and if i serach b then will show expander having a and inside content it only show b and bt.

Below is my binding structure .

private ObservableCollection<FontDetail> _fontDetail;
public ObservableCollection<FontDetail> FontDetailList
{
    get
    {
        return _fontDetail;
    }
}

    FontDetail
    {
        public FamilyChild fontChild { get; set; }
        //ContextMenu End

        public bool IsFamily { get; set; }
        public int TotalFonts { get; set; }
        public List<FamilyChild> FamilyChildList { get; set; }
    }

    public class FamilyChild
    {
        public FontStatus Status { get; set; }


        public long TimeToAdd { get; set; }
        public FontType FontType { get; set; }
        public string SampleText { get; set; }
        public string Name { get; set; }
        public string FontFamily { get; set; }
        public string FontStyle { get; set; }
        public long FontWeight { get; set; }
        public string FontId { get; set; }

        public string MenuItem1 { get; set; }
        public string MenuItem2 { get; set; }
        public string MenuItem3 { get; set; }

        public bool IsEnableMenuItem1 { get; set; }
        public bool IsEnableMenuItem2 { get; set; }
        public bool IsEnableMenuItem3 { get; set; }
    }

So I have binded ListBox with FontDetailList. Now I wanted to apply filter on FontDetail as well as FamilyChildList. FontDetail bind in Expander header and FamilyChildList is bind as a content of expander.


Solution

  • You have to apply Filter two times. First for outer collection, then apply second Filter in Filter predicate of outer collection. Below code filter employees whose vehicle names start with "S", and shows Employee name and vehicle list.

    DataStore contains EmployeeList, Employee contains VehicleList

            private void BtnFilter_Click(object sender, RoutedEventArgs e)
            {
                var source = CollectionViewSource.GetDefaultView(Dgrd.ItemsSource);            
                source.Filter = new Predicate<object>(FilterEmployees);            
    
                source.Refresh();
            }
    
            private bool FilterEmployees(object o)
            {
                DB1.Employee e = o as DB1.Employee;
    
                var vehicles = CollectionViewSource.GetDefaultView(e.Vehicles);
                vehicles.Filter = new Predicate<object>(FilterVehicles);
    
                return (e.Vehicles.Where(v=>v.Name.StartsWith("S"))).Count() > 0;
            }
    
            private bool FilterVehicles(object obj)
            {
                DB1.Vehicle v = obj as DB1.Vehicle;
                return v.Name.StartsWith("S");
            }
    

    Filtering output