Losec
Losec

Reputation: 105

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

Upvotes: 0

Views: 329

Answers (2)

Anton Semenov
Anton Semenov

Reputation: 6347

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

Upvotes: 1

SledgeHammer
SledgeHammer

Reputation: 7680

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.

Upvotes: 1

Related Questions