CollectionViewSource Логика фильтрации - PullRequest
0 голосов
/ 29 сентября 2010

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

Что меня особенно смущает, так это то, как запускать представление для фильтрации при изменении различных критериев фильтрации(см. _ApplyFiler (), ниже).Правильно ли настроен фильтр?Где я должен отписаться / установить его на нуль после фильтрации?

Cheers, Berryl

некрасивый код:

public class SubjectPickerBase<T> : ViewModelBase, ISubjectPicker<T> 
    where T : class, IAvailableItem, INotifyPropertyChanged, IActivitySubject
{
    public CollectionViewSource Subjects { get; private set; }

    protected SubjectPickerBase() { }

    protected void _Initialize(IEnumerable<T> subjects, string subjectName) {
        ...

        Subjects = new CollectionViewSource { Source = subjects };
        _ApplyFilter();
    }

    protected void _ApplyFilter() {
        Subjects.View.Filter += Filter;
    }

    private bool Filter(object obj)
    {
        var subject = obj as T;
        if (ReferenceEquals(subject, null)) return false;

        NotifyPropertyChanged(() => Status);

        var isIncludedBySubclass = OnFilter(subject);
        var isIncludedByBase = subject.IsAvailable;
        return isIncludedByBase & isIncludedBySubclass;
    }

    /// <summary>Hook to allow implementing subclass to provide it's own filter logic</summary>
    protected virtual bool OnFilter(T subject) { return true; }


 }

public class ProjectSelectionViewModel : SubjectPickerBase<ProjectViewModel>
{

    public ProjectSelectionViewModel(IEnumerable<ProjectViewModel> projects) 
    {
        ...
        _Initialize(projects, Strings.ActivitySubject__Project);
    }

    public string DescriptionMatchText {
        get { return _descriptionMatchText; }
        set {
            ApplyPropertyChange<ProjectSelectionViewModel, string>(ref _descriptionMatchText, x => x.DescriptionMatchText, value);
            _ApplyFilter();
        }
    }
    private string _descriptionMatchText;

    protected override bool OnFilter(ProjectViewModel subject)
    {
        ...
        var isDescriptionMatch = subject.IsMatch_Description(DescriptionMatchText);
        return isPrefixMatch && isMidfixMatch && isSequenceNumberMatch && isDescriptionMatch;
    }

}

1 Ответ

1 голос
/ 02 октября 2010

Есть несколько частей для нетривиальной манипуляции с представлением, которое я пропустил, все они связаны с обновлением CollectionView, которое является свойством CollectionViewSource:

Первая часть моего вопроса была о том, когда установить фильтр. Для моего случая использования лучше всего оказалось зарегистрироваться для события CollectionViewSource.Filter, а затем использовать метод View.Refresh при каждом изменении фильтра. Первоначальная регистрация события фильтра также запускает обработчик событий, и многие из примеров msdn, которые вы видите, показывают это как способ фильтрации представления и ничего более. Но если ваш сценарий не тривиален, и пользователь может изменить некоторые критерии фильтрации, вам необходимо использовать один или несколько из перечисленных выше методов и свойств, связанных с обновлением.

Вторая часть моего вопроса была связана с тем, нужно ли вам отказаться от подписки на событие фильтра, и если да, то когда. Что ж, получается, что вам не нужно , чтобы отписаться от подписки, но если вы сделаете это, это эффективно очистит любую фильтрацию представления. И многие из тривиальных примеров msdn делают именно это, чтобы очистить фильтр, что, безусловно, нужно, если вы хотите полностью очистить фильтрацию, но для моего случая использования это было не то, что я действительно хотел. Я хотел очистить некоторые критерии, но не другие, и снова использование Refresh (в нужное время) дало мне желаемое поведение.

НТН,
Berryl

...