在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-element-notation设置该处理程序)

实际上您甚至不需要访问CollectionViewSource实例,您可以直接在ViewModel中过滤源集合:

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

(注意ICollectionView.Filter不是像CollectionViewSource.Filter这样的事件,它是Predicate类型的属性)

WPF自动创建一个CollectionView或派生类型,如ListCollectionViewBindingListCollectionView等(它取决于您的源集合中检测到的function) – 对于任何ItemsSource绑定,如果您绑定IEnumerable时不提供一个 -派生源直接到ItemsControl.ItemsSource属性。

这个自动提供的CollectionView实例由系统基于每个集合创建和维护(注意: 不是每个UI控件或绑定目标 )。 换句话说,对于您绑定的每个 ,将只有一个全局共享的“Default”视图,并且可以通过将IEnumerable传递给静态方法CollectionViewSource.GetDefaultView()来随时检索(或按需创建)此唯一的CollectionView实例。 CollectionViewSource.GetDefaultView()

有时即使您尝试将自己特定的CollectionView派生类型显式绑定到ItemsSource ,WPF数据绑定引擎也可以将其包装(使用内部类型CollectionViewProxy )。

在任何情况下,每个带有数据绑定ItemsSource属性的ItemsControl总是会有一些排序和过滤function,这可以通过一些流行的CollectionView 。 您可以通过抓取并操纵其“默认” CollectionView轻松地对任何给定的IEnumerable执行过滤/排序,但请注意UI中最终使用该视图的所有数据绑定目标 – 要么是因为您明确绑定到CollectionViewSource.GetDefaultView() ,或者因为你根本没有提供任何视图 – 都将共享相同的排序/过滤效果。

除了将源集合绑定 ItemsControlItemsSource属性(作为绑定目标 )之外,在此主题上不经常提到的是,您还可以“同时” 访问应用的filter/排序结果的有效集合 –暴露为一个CollectionView派生的System.Windows.Controls.ItemCollection实例 – 来自 Control的Items属性的绑定(作为绑定 )。

这可以实现众多简化的XAML场景:

  1. 如果对于给定的IEnumerable源具有单个全局共享的filter/排序function对您的应用程序来说已经足够,那么只需直接绑定到ItemsSource 。 仍然只在XAML中 ,您可以通过将相同Control上的Items属性视为ItemCollection绑定来过滤/排序项目。 它有许多有用的可绑定属性来控制filter/排序。 如上所述,过滤/排序将在以这种方式绑定到相同源IEnumerable所有UI元素之间共享。 – 要么 –

  2. 自己创建并应用一个或多个不同的(非“默认”) CollectionView实例。 这允许每个数据绑定目标具有独立的filter/排序设置。 这也可以在XAML中完成,和/或您可以创建自己的(List)CollectionView派生类。 这种方法在其他地方有很好的涵盖,但我想在这里指出的是,在许多情况下,通过使用与ItemsControl.Items属性 (作为绑定 )相同的数据绑定技术,可以简化XAML。为了访问有效的CollectionView

简介:仅使用XAML ,您可以通过将其Items属性视为只读绑定 ,将数据绑定到表示WPF ItemsControl上任何当前CollectionView过滤/排序的有效结果CollectionView 。 这将是一个System.Windows.Controls.ItemCollection ,它公开可绑定/可变属性以控制活动filter和排序条件。


[编辑 – 进一步的想法:]
请注意,在将IEnumerable直接绑定到ItemsSource的简单情况下,您可以绑定到ItemsControl.ItemsItemCollection将是原始集合的CollectionViewSource.GetDefaultView()的包装器。 如上所述,在XAML使用中,绑定到此UI包装器(通过ItemsControl.Items )是一个明智的选择,而不是绑定到它包装的底层视图(通过CollectionViewSource.GetDefaultView ),因为前一种方法可以节省您的麻烦否则提到CollectionView

但更进一步,因为ItemCollection 包装了默认的CollectionView ,在我看来,即使在代码隐藏 (选择不太明显)的情况下,它也可能更加实用,可以绑定到UI发布的视图,因为这样可能更好地适应到数据源及其UI控件目标的function。