How can an attached behavior be added to a CollectionViewSource?

最后都变了- 提交于 2019-12-22 11:23:36

问题


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.

The XAML looks like the following:

<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 appears to be a DependencyObject. I'm not sure what I'm doing wrong.

The following is the behavior code:

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>();
}

回答1:


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



来源:https://stackoverflow.com/questions/10466691/how-can-an-attached-behavior-be-added-to-a-collectionviewsource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!