Reputation: 1744
I have a class that represents a collection and implements, amongst others, the following interfaces:
IEnumerable
so that I can bind a WPF ItemsControl.ItemsSource
to it.ICollectionViewFactory
to use a view I can configure instead of creating a default viewSo far, all is fine: I can bind a control, including sorting, filtering and even "live shaping".
First question: Due to the ICollectionViewFactory
the IEnumerable.GetEnumerator
is never called (by the UI), but it still appears to be required. Should I be smelling something here?
Then, I have one specific scenario where I want to do some additional filtering and the criteria will depend on the render context which is why I thought I'd use an IValueConverter
with something like this:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var cv = (ICollectionViewFactory)value.CreateView();
cv.ExtendFilter(i => i.AdditionalFilterProperty);
return cv;
}
The ExtendFilter
extension method looks like this:
public static void ExtendFilter(this ICollectionView view, Predicate<object> filter)
{
if (view.Filter == null)
{
view.Filter = filter;
}
else
{
var originalFilter = view.Filter;
view.Filter = item => originalFilter(item) && filter(item);
}
}
Second question: Is there a better way to do this? I was thinking, maybe, expression trees...
Upvotes: 0
Views: 191
Reputation: 20461
Firstly, it is correct that IEnumerable
isnt called if your collection class implements ICollectionViewFactory
.
Deep in the WPF framework the ItemsSource
(IEnumerable
) has its default collection view created. In that code, if the collection already implements ICollectionViewFactory
then it takes CreateView
as the actual items source. If it doesnt implement it then it creates a default view with the IEnumerable
as the items source.
Secondly, your composite filter logic seems reasonable. Expression trees take a lot more implementing, but would also provide a good solution also. Personally I would stick with what you have
Upvotes: 1