17

本当に主題はそれをすべて言います。

<CollectionViewSource x:Key="MyData"
    Source="{Binding}" Filter="{ SomethingMagicInXaml? }" />

コードを後回しにできないわけではありません。それはただ私をしつこくします。

4

3 に答える 3

24

XAML では、プログラム全体を作成するまで、「十分に努力」すれば、ほとんど何でも行うことができます。

コード ビハインドを回避することはありません (ライブラリを使用する場合、ライブラリを作成する必要はありませんが、アプリケーションはもちろんライブラリに依存しています)。この特定のケースで実行できることの例を次に示します。

<CollectionViewSource x:Key="Filtered" Source="{Binding DpData}"
                      xmlns:me="clr-namespace:Test.MarkupExtensions">
    <CollectionViewSource.Filter>
        <me:Filter>
            <me:PropertyFilter PropertyName="Name" Value="Skeet" />
        </me:Filter>
    </CollectionViewSource.Filter>
</CollectionViewSource>
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<IFilter> _filters = new Collection<IFilter>();
        public ICollection<IFilter> 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.FilterIntelliSense に表示される場合、XML-element-notation を介してそのハンドラーを設定する必要はありません)

于 2011-06-24T01:05:04.700 に答える
18

実際には、インスタンスにアクセスする必要さえありませんCollectionViewSource。ViewModel でソース コレクションを直接フィルタリングできます。

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

ICollectionView.Filter( のようなイベントではなく、CollectionViewSource.Filtertype のプロパティであることに注意してくださいPredicate<object>)

于 2011-06-24T01:13:45.303 に答える