如何将附加行为添加到 CollectionViewSource? [英] How can an attached behavior be added to a CollectionViewSource?

查看:24
本文介绍了如何将附加行为添加到 CollectionViewSource?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向 CollectionViewSource 添加附加行为,以便我可以在 XAML 中的视图模型上提供过滤器 Predicate 属性.

I am trying to add an attached behavior to a CollectionViewSource so that I can provide a filter Predicate property on my view-model in XAML.

XAML 如下所示:

<DataGrid ItemsSource="{Binding}">
    <DataGrid.DataContext>
        <CollectionViewSource Source="{Binding Path=Items}"
                 acb:CollectionViewSourceItemFilter.ItemFilter="{Binding Path=ItemFilter}" />
    </DataGrid.DataContext>
</DataGrid>

但是,我收到一个错误:

However, I am getting an error:

A 'Binding' cannot be set on the 'SetItemFilter' property of type   
'CollectionViewSource'. A 'Binding' can only be set on a DependencyProperty of a 
DependencyObject.

CollectionViewSource 似乎是一个 DependencyObject.我不确定我做错了什么.

CollectionViewSource appears to be a DependencyObject. I'm not sure what I'm doing wrong.

以下是行为代码:

public static class CollectionViewSourceItemFilter
{
    /// <summary>
    /// Gets the property value.
    /// </summary>
    public static Predicate<object> GetItemFilter(CollectionViewSource collectionViewSource)
    {
        return (Predicate<object>)collectionViewSource.GetValue(ItemFilter);
    }

    /// <summary>
    /// Sets the property value.
    /// </summary>
    public static void SetItemFilter(CollectionViewSource collectionViewSource, Predicate<object> value)
    {
        collectionViewSource.SetValue(ItemFilter, value);
    }

    /// <summary>
    /// The ItemFilter dependency property.
    /// </summary>
    public static readonly DependencyProperty ItemFilter =
        DependencyProperty.RegisterAttached(
        "ItemFilter",
        typeof(Predicate<object>),
        typeof(ItemFilterBehavior),
        new UIPropertyMetadata(null, OnItemFilterChanged));

    private static void OnItemFilterChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        CollectionViewSource collectionViewSource = depObj as CollectionViewSource;
        if (collectionViewSource == null)
            return;

        if (!Equals(e.NewValue, e.OldValue))
        {
            var newFilter = (Predicate<object>)e.NewValue;

            // Remove any previous filter.
            ItemFilterBehavior oldBehavior;
            if (behaviors.TryGetValue(collectionViewSource, out oldBehavior))
            {
                oldBehavior.Unregister();
                behaviors.Remove(collectionViewSource);
            }

            if (newFilter != null)
                behaviors.Add(collectionViewSource, new ItemFilterBehavior(collectionViewSource, newFilter));
        }
    }

    private class ItemFilterBehavior
    {
        public ItemFilterBehavior(CollectionViewSource collectionViewSource, Predicate<object> filter)
        {
            _collectionViewSource = collectionViewSource;
            _filter = filter;
            _collectionViewSource.Filter += collectionViewSource_Filter;
        }

        void collectionViewSource_Filter(object sender, FilterEventArgs e)
        {
            e.Accepted = _filter(e.Item);
        }

        public void Unregister()
        {
            _collectionViewSource.Filter -= collectionViewSource_Filter;
        }

        private readonly CollectionViewSource _collectionViewSource;
        private readonly Predicate<object> _filter;
    }

    private static readonly IDictionary<CollectionViewSource, ItemFilterBehavior> behaviors = new ConcurrentDictionary<CollectionViewSource, ItemFilterBehavior>();
}

推荐答案

在问题中发布行为代码让我弄清楚了.我的 DependencyProperty 使用 ItemFilterBehavior 而不是 CollectionViewSourceItemFilter 作为所有者类型.

Posting the behavior code in the question led me to figure it out. My DependencyProperty used ItemFilterBehavior instead of CollectionViewSourceItemFilter as the owner type.

这篇关于如何将附加行为添加到 CollectionViewSource?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆