В WPF можно фильтровать CollectionViewSource без кода?

На самом деле предмет говорит все.

 

Не то, чтобы у меня не было кода. Он просто дергает меня.

Вы можете сделать что угодно в XAML, если вы «достаточно стараетесь», вплоть до написания в нем целых программ .

Вы никогда не обойдете код (ну, если вы используете библиотеки, вам не нужно писать, но приложение все равно полагается на это, конечно), вот пример того, что вы можете сделать в этом конкретном случае:

        
 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Markup; using System.Windows.Data; using System.Collections.ObjectModel; using System.Windows; using System.Text.RegularExpressions; namespace Test.MarkupExtensions { [ContentProperty("Filters")] class FilterExtension : MarkupExtension { private readonly Collection _filters = new Collection(); public ICollection Filters { get { return _filters; } } public override object ProvideValue(IServiceProvider serviceProvider) { return new FilterEventHandler((s, e) => { foreach (var filter in Filters) { var res = filter.Filter(e.Item); if (!res) { e.Accepted = false; return; } } e.Accepted = true; }); } } public interface IFilter { bool Filter(object item); } 
  // Sketchy Example Filter public class PropertyFilter : DependencyObject, IFilter { public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register("PropertyName", typeof(string), typeof(PropertyFilter), new UIPropertyMetadata(null)); public string PropertyName { get { return (string)GetValue(PropertyNameProperty); } set { SetValue(PropertyNameProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(PropertyFilter), new UIPropertyMetadata(null)); public object Value { get { return (object)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonly DependencyProperty RegexPatternProperty = DependencyProperty.Register("RegexPattern", typeof(string), typeof(PropertyFilter), new UIPropertyMetadata(null)); public string RegexPattern { get { return (string)GetValue(RegexPatternProperty); } set { SetValue(RegexPatternProperty, value); } } public bool Filter(object item) { var type = item.GetType(); var itemValue = type.GetProperty(PropertyName).GetValue(item, null); if (RegexPattern == null) { return (object.Equals(itemValue, Value)); } else { if (itemValue is string == false) { throw new Exception("Cannot match non-string with regex."); } else { return Regex.Match((string)itemValue, RegexPattern).Success; } } } } } 

Расширения разметки – ваш друг, если вы хотите что-то сделать в XAML.

(Возможно, вы захотите указать имя расширения, то есть me:FilterExtension поскольку проверка «на лету» в Visual Studio может жаловаться без причины, она все еще компилируется и запускается, но предупреждения могут быть раздражающими.
Также не ожидайте, что CollectionViewSource.Filter появится в IntelliSense, он не ожидает, что вы установите этот обработчик через XML-элемент-нотацию)

На самом деле вам даже не нужен доступ к экземпляру CollectionViewSource , вы можете фильтровать исходную коллекцию непосредственно в ViewModel:

 ICollectionView view = CollectionViewSource.GetDefaultView(collection); view.Filter = predicate; 

(обратите внимание, что ICollectionView.Filter не является событием вроде CollectionViewSource.Filter , это свойство типа Predicate )

WPF автоматически создает тип CollectionView или производный тип, такой как ListCollectionView , BindingListCollectionView и т. Д. (Зависит от возможностей, обнаруженных в вашей исходной коллекции) – для любой привязки ItemsSource , если вы не поставляете его, когда вы связываете свой IEnumerable – напрямую к объекту ItemsControl.ItemsSource .

Этот автоматически созданный экземпляр CollectionView создается и поддерживается системой по принципу сбора данных (обратите внимание: не на контроль пользовательского интерфейса или на привязку). Другими словами, для каждого источника, к которому вы привязываетесь, будет отображаться ровно один глобальный общий «По умолчанию», и этот уникальный экземпляр CollectionView может быть извлечен (или создан по требованию) в любое время, передав IEnumerable статическому методу CollectionViewSource.GetDefaultView() .

Иногда даже если вы попытаетесь явно привязать свой собственный тип CollectionView -derived к элементу ItemsSource , механизм привязки данных WPF может обернуть его (используя внутренний тип CollectionViewProxy ).

В любом случае, каждый элемент ItemsControl с привязанным к данным свойством ItemsSource всегда будет иметь возможности сортировки и фильтрации, любезно предоставленные некоторыми элементами CollectionView . Вы можете легко выполнить фильтрацию / сортировку для любого данного IEnumerable , захватив и манипулируя своим «Default» CollectionView , но обратите внимание, что все привязанные к данным цели в пользовательском интерфейсе, которые в конечном итоге используют это представление, либо потому, что вы явно привязаны к CollectionViewSource.GetDefaultView() , или потому, что вы вообще не предоставили никакого представления – все они будут иметь одни и те же эффекты сортировки / фильтрации.

То, что не часто упоминается в этом вопросе, заключается в том, что в дополнение к привязке исходной коллекции к свойству ItemsSource элемента ItemsControl (как к цели привязки) вы также можете «одновременно» получить доступ к эффективной коллекции прикладных результатов фильтрации / сортировки – экземпляр CollectionView обработанный System.Windows.Controls.ItemCollection связанный с Items элемента управления (как источник привязки).

Это позволяет использовать многочисленные упрощенные сценарии XAML:

  1. Если для вашего приложения достаточно одного глобального фильтра / возможности сортировки для данного источника IEnumerable , просто привяжите его непосредственно к ItemsSource . Тем не менее, только в XAML вы можете фильтровать / сортировать элементы, обрабатывая свойство Items в том же ItemCollection управления, что и ItemCollection привязки ItemCollection . Он имеет много полезных связующих свойств для управления фильтром / сортировкой. Как отмечено, фильтрация / сортировка будет разделена между всеми элементами пользовательского интерфейса, которые таким образом связаны с одним и тем же источником IEnumerable . –или–

  2. Создайте и примените один или несколько отдельных (нестандартных) экземпляров CollectionView самостоятельно. Это позволяет каждому объекту, связанному с данными, иметь независимые настройки фильтра / сортировки. Это также можно сделать в XAML и / или вы можете создать свои собственные (List)CollectionView -удаленные classы. Этот тип подхода хорошо освещен в другом месте, но я хотел бы отметить здесь, что во многих случаях XAML можно упростить, используя тот же метод привязки данных к свойству ItemsControl.Items (как источник привязки) в чтобы получить доступ к эффективному CollectionView .

Резюме. Только с XAML вы можете привязать данные к коллекции, представляющей эффективные результаты любой текущей фильтрации / сортировки CollectionView в WPF ItemsControl , рассматривая ее свойство Items как источник привязки только для чтения. Это будет System.Windows.Controls.ItemCollection который предоставляет свойства bindable / mutable для управления активным фильтром и критериями сортировки.


[edit – дальнейшие мысли:]
Обратите внимание, что в простом случае привязки IEnumerable непосредственно к ItemsSource , ItemCollection , с ItemCollection вы можете привязываться в ItemsControl.Items будет оболочкой коллекции CollectionViewSource.GetDefaultView() исходной коллекции. Как обсуждалось выше, в использовании XAML нет необходимости связываться с этой оболочкой UI (через ItemsControl.Items ), в отличие от привязки к базовому представлению, которое оно обертывает (через CollectionViewSource.GetDefaultView ), поскольку прежний подход избавляет вас от неприятностей иначе упоминать CollectionView вообще.

Но, поскольку этот ItemCollection обертывает CollectionView по умолчанию, мне кажется, что даже в кодировке (где выбор менее очевиден), возможно, более целесообразно связываться с представлением, обнародованным пользовательским интерфейсом, поскольку такое, вероятно, лучше настроено к возможностям как источника данных, так и его цели управления пользовательским интерфейсом.

  • WPF DataGrid - кнопка в столбце, получающая строку, из которой она появилась в обработчике событий Click
  • Как открыть всплывающее окно WPF при нажатии другого элемента управления, используя только разметку XAML?
  • Почему ActualWidth и ActualHeight 0.0 в этом случае?
  • WPF Binding - значение по умолчанию для пустой строки
  • Стили сплава XAML
  • Новая строка в атрибуте string
  • Как растянуть WPF вкладку Элементы заголовка к размеру родительского контроля
  • Имя не существует в ошибке пространства имен в XAML
  • Связывание в текстовом столбце таблицы данных WPF
  • Добавление элементов в столбцы в WPF ListView
  • Как WPF UserControl наследует WPC UserControl?
  • Давайте будем гением компьютера.