I think I understand what you need, this should start.
I assume that your usercontrol has two lists intended for true elements named "TrueList" and the other for false elements named "FalseList".
Extend your usercontrol from the ItemsCollection and bind the ItemsSource property of each list to the ItemsSource of the parent usercontrol.
Add the TrueFilter and FalseFilter property to your usercontrol:
Predicate<object> trueFilter; public Predicate<object> TrueFilter { get { return trueFilter; } set { if (trueFilter!= null && this.TrueList.Items != null) this.TrueList.Items.Filter -= trueFilter; trueFilter = value; if (trueFilter!= null && this.TrueList.Items != null) this.TrueList.Items.Filter += trueFilter; } } Predicate<object> falseFilter; public Predicate<object> FalseFilter { get { return falseFilter; } set { if (falseFilter!= null && this.FalseList.Items != null) this.FalseList.Items.Filter -= falseFilter; filter = value; if (falseFilter!= null && this.FalseList.Items != null) this.FalseList.Items.Filter += falseFilter; } }
Then create the “IToggle” interface (or another more meaningful name):
public interface IToggle { Predicate<object> TrueFilter { get; } Predicate<object> FalseFilter { get; } }
Then continue with the ObservableCollection for each of your custom classes, implementing the "IToggle" interface:
public class Cars : ObservableCollection<Car>, IToggle { Predicate<object> trueFilter; public Predicate<object> TrueFilter { get { if (trueFilter == null) trueFilter = new Predicate<object>(this.TrueFilterPredicate); return trueFilter; } } private bool TrueFilterPredicate(object value) { Car car = (Car)value; return car.IsFast; } Predicate<object> falseFilter; public Predicate<object> FalseFilter { get { if (falseFilter == null) falseFilter = new Predicate<object>(this.FalseFilterPredicate); return falseFilter; } } private bool FalseFilterPredicate(object value) { Car car = (Car)value; return !car.IsFast; }
Then override the ItemsSource property of your user control:
public new IEnumerable ItemsSource { get { return base.ItemsSource; } set { if (value != null && !(value is IToggle)) throw new Exception("You may only bind this control to collections that implement IToggle."); base.ItemsSource = value; this.TrueFilter = base.ItemsSource == null ? null : (base.ItemsSource as IToggle).TrueFilter; this.FalseFilter = base.ItemsSource == null ? null : (base.ItemsSource as IToggle).FalseFilter; } }
Finally, call TrueList.Items.Refresh () and FalseList.Items.Refresh () in your event callbacks to update the element views each time the element switches from true to false and vice versa.
This solution still requires writing implementation code for each custom class (true and false filters), but it should contain minimal code.
Alternatively, this would be much simpler if you provided each of your user classes with a common interface, for example:
public interface Valid { bool IsValid { get; set; } }
Then you can use one set of filters (or style installers or data binding to converters) to work with the "Valid" interface. Instead of Car.IsFast and Fruit.ILikeIt, you will use Car.IsValid and Fruit.IsValid.