我正在尝试将附加行为添加到 CollectionViewSource,以便我可以在 XAML 中的视图模型上提供过滤谓词属性。
XAML 如下所示:
<DataGrid ItemsSource="{Binding}">
<DataGrid.DataContext>
<CollectionViewSource Source="{Binding Path=Items}"
acb:CollectionViewSourceItemFilter.ItemFilter="{Binding Path=ItemFilter}" />
</DataGrid.DataContext>
</DataGrid>
但是,我收到一个错误:
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。我不确定我做错了什么。
以下是行为代码:
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>();
}