views:

7359

answers:

5

Hi

I want to make a UI virtualization via the datasource.

The idea is to "Filter" what i send to the UI (a listbox in my case).

I noticed that the ItemsSource (an observable collection) is read once and that changing the Filter does not trigger refreshing...

I don't understand why Thanks Jonathan

A: 

What filter are you talking about? If you are a CollectionView and then binding to that then there won't be a changed even for the control to pick up on.

Steven Robbins
A: 

I'll try to be more clear :

I have CollectionViewSource:

<CollectionViewSource x:Key="MyItemView"
                                  Source="{Binding Path=Model.CurrentItem}" />

Then use this datasource in my ListBox:

<ListBox x:Name="myListBox"
                 ItemsSource="{Binding Source={StaticResource MyItemView}}"

I thought to implement a converter that would return a filtered collection (base on the current date):

<ListBox x:Name="myListBox"
                 ItemsSource="{Binding Source={StaticResource MyItemView}, Converter={StaticResource FilterByTime}, ConverterParameter=CurrentDate }"

Which i implemented this way:

public class FilterByTimeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                System.Windows.Data.ListCollectionView list = value as System.Windows.Data.ListCollectionView;

                var model = DI.Resolve<ApplicationModel>();

                list.Filter = delegate(object item) 
                { 
                    bool r= (((MyModel)item).OriginalDate > model.TimeLine.CurrentDate.AddMonths(-1) 
                        && (((MyModel)item).OriginalDate < model.TimeLine.CurrentDate.AddMonths(1)));

                   // Console.WriteLine ("{0}<{1}<{2} : {3}",model.MyListBox.CurrentDate.AddMonths(-1),((MyModel)item).OriginalDate ,model. MyListBox.CurrentDate.AddMonths(1),r.ToString());
                    return r;
                };

                return list;
            }

            return DependencyProperty.UnsetValue;
        }

This works fine...but only when bounf the first time. When the Current Date is changed and that the filter is changed, the list is not updated.

Perhaps i should listen to the CurrentDate PropertyChange, but i'm confused how to do this

Thanks Jonathan

You should edit your original question with this information so that people don't miss it. You can do this by looking at your question, just under the tags there will be an "edit" link that will allow you to add the extra information.
Bryan Anderson
+6  A: 

The CollectionViewSource itself supports filtering via its Filter property. Why don't you put your filtering logic in there?

HTH, Kent

Kent Boogaart
See Bea Stollnitz for an example: http://www.beacosta.com/blog/?p=31
Bryan Anderson
+3  A: 

You might want to manually refresh:

currentViewSource.View.Refresh()
Arcturus
+2  A: 

Well, I had similar issue, but came with the following solution that works for me:

Supposedly, the combobox shows the list of authors and the listbox all books and I want to filter the books by selected author or show all books unfiltered.

The pertinent window XAML fragment:

<ComboBox ItemsSource="{Binding Authors}"  DisplayMemberPath="FullName" SelectedValue="{Binding FilterAuthorBy, Mode=TwoWay}" />
<ListBox Name="bookList" ItemsSource="{Binding Books}"/>

Binding itself is done like this on the window constructor:

DataContext = new BookViewModel(this);

And the view model is defined as such:

public class BookViewModel
{
   private Author _filterAuthorBy;

   public BookViewModel(IBookView view)
   {
      ...
      _books = new CollectionViewSource();
      _books.Source = _bookRepository.FindAll().ToArray();
      _books.Filter += (sender, e) =>
                         {
                             Book book = e.Item as Book;
                             if (_filterAuthorBy == null)
                             {
                                 e.Accepted = true;
                             }
                             else
                             {
                                 e.Accepted = book.Authors.Contains(_filterAuthorBy);
                             }
                         };
   }

   public CollectionView Books
   {
       get
       {               
           return _books.View;
       }
   }

   public ObservableCollection<Author> Authors
   {
      get
      {
         return new ObservableCollection<Author>(_bookRepository.FindAllAuthors());
      }
   }

   public Author FilterAuthorBy
   {
       get
       {
           return _filterAuthorBy;
       }
       set
       {
           _filterAuthorBy = value;
           _books.View.Refresh();
       }
    } 
}

The selected author is passed down to the ViewModel and the listbox is updated by calling collectionViewSource.View.Refresh()

Arunas