ListBox ItemsSource динамический фильтр WPF - PullRequest
4 голосов
/ 12 января 2009

Я хочу сделать виртуализацию пользовательского интерфейса через источник данных.

Идея состоит в том, чтобы «фильтровать» то, что я посылаю в пользовательский интерфейс (список в моем случае).

Я заметил, что ItemsSource (наблюдаемая коллекция) читается один раз и что изменение фильтра не вызывает обновления ...

Я не понимаю, почему Спасибо Jonathan


Я постараюсь быть более ясным:

У меня есть CollectionViewSource:

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

Затем используйте этот источник данных в моем ListBox:

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

Я подумал реализовать конвертер, который бы возвращал отфильтрованную коллекцию (основываясь на текущей дате):

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

Что я реализовал так:

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

Это работает нормально ... но только когда прыгаешь в первый раз. При изменении текущей даты и изменении фильтра список не обновляется.

Возможно, мне стоит послушать CurrentDate PropertyChange, но я запутался, как это сделать

Спасибо Jonathan

Ответы [ 4 ]

9 голосов
/ 12 января 2009

CollectionViewSource сам поддерживает фильтрацию через свойство Filter. Почему бы вам не поставить свою логику фильтрации там?

6 голосов
/ 20 октября 2009

Ну, у меня была похожая проблема, но пришло со следующим решением, которое работает для меня:

Предположительно, в комбинированном списке отображаются список авторов и список всех книг, и я хочу отфильтровать книги по выбранному автору или показать все книги без фильтра.

Соответствующий фрагмент XAML окна:

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

Сама привязка выполняется в конструкторе окна следующим образом:

DataContext = new BookViewModel(this);

И модель вида определяется так:

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

Выбранный автор передается в ViewModel, а список обновляется путем вызова collectionViewSource.View.Refresh ()

4 голосов
/ 12 января 2009

Возможно, вы захотите обновить вручную:

currentViewSource.View.Refresh()
0 голосов
/ 12 января 2009

О каком фильтре вы говорите? Если вы CollectionView и затем привязываетесь к нему, то не будет изменений даже для элемента управления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...