简体   繁体   中英

Filtering ObservableCollection using Command

Here is my ViewModel :

This is bound to my datagrid and loads all my data the issue I am having is I have made a radio button bound to a command and when it is selected I want it to "filter" my FullItemList to only show the empty rows in my datagrid.

    public class ResidentViewModel
{
    public ResidentViewModel()
    {
        AllRooms();
    }
    public ObservableCollection<Res_details> FullItemList { get; set; }

    private void AllRooms()
    {
        var items = new ObservableCollection<Res_details>();
        using (var db = new Access5687DB())
        {
            var q =
                from c in db.Residents
                select c;
            foreach (var c in q)
            {
                items.Add(new Res_details()
                {
                    ID = c.Room,
                    Name = c.Firstname,
                    LastName = c.Lastname,
                    Birthday = c.Birthday,
                    Arrival = c.Admission,
                });
            }
            FullItemList = items;
        }
    }

    private ICommand filter_Empty;
    public ICommand Filter_Empty
    {
        get { if (filter_Empty == null) filter_Empty = new FilterObs(); return filter_Empty; }
        set { filter_Empty = value; }
    }

    private class FilterObs : ICommand
    {
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            if ((string)parameter == "B")
                return
                    true;
            if ((string)parameter != "B")
                return
                    false;
            else
                return
                    false;
        }

        public void Execute(object parameter)
        {
              #Something needs to go here.
        }
    }
}

Wrap your ObservableCollection in a CollectionViewSource and bind that to the DataGrid instead. CollectionViewSource has a Filter callback. Call CollectionViewSource.View.Refresh() if you want to change the filter.

I agree with SledgeHammer, to use ICollectionView is best solution here. To gain asscess to your view model inside filter command, you need to pass viewModel reference into your command or you can pass only delegate, as shown below (pseudo code)

public class ResidentViewModel
{
    public ResidentViewModel()
    {
        FullItemList = CollectionViewSource.GetDefaultView(_itemList);
        Load();
    }

    private ObservableCollection<Res_details> _itemList { get; set; }
    public ICollectionView FullItemList { get; private set; }

    private void Load()
    {
        var items = new ObservableCollection<Res_details>();
        using (var db = new Access5687DB())
        {
            var q =
                from c in db.Residents
                select c;
            foreach (var c in q)
            {
                items.Add(new Res_details()
                {
                    ID = c.Room,
                    Name = c.Firstname,
                    LastName = c.Lastname,
                    Birthday = c.Birthday,
                    Arrival = c.Admission,
                });
            }
            _fullItemList = items;
        }
    }

    /*Apply filter to the collection view*/
    private void ShowEmptyLinesOnly(object parameter)
    {
        /*logic based on your parameter here*/


        FullItemList.Filter = FilterEmptyLine;//<-- set filter to collection view
        FullItemList.Refresh();
    }

    private bool FilterEmptyLine(object o)
    {
        var item = o as Res_details;
        if (item == null) return false;

        /*
         * decide if item is 'empty' and return true in case item is empty;
         */
    }

    private ICommand filter_Empty;
    public ICommand Filter_Empty
    {
        get { if (filter_Empty == null) filter_Empty = new FilterObs(ShowEmptyLinesOnly); return filter_Empty; }
        set { filter_Empty = value; }
    }

    private class FilterObs : ICommand
    {
        public event EventHandler CanExecuteChanged;
        private readonly Action<object> _filterAction;

        public FilterObs(Action<object> filterAction)
        {
            _filterAction = filterAction;
        }

        public bool CanExecute(object parameter)
        {
            if ((string)parameter == "B")
                return
                    true;
            if ((string)parameter != "B")
                return
                    false;
            else
                return
                    false;
        }

        public void Execute(object parameter)
        {
            _filterAction.Invoke(parameter);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM