如果你把它减少到一个类,问题就很简单了。给定下图,我想创建一个简单的双面控件,它根据 bool 值将一个列表中的项目放入另一个列表中。
编辑:您当然可以单击两个列表中的项目,然后该项目切换到另一个列表。此外,还会调用回调,以防我需要更新一些数据库内容......
我创造了一张漂亮的照片来让你有点兴奋,因为我被困住了......
世界并不像例子那么简单:您将如何为各种类(class)解决这个问题。
想象一下带有“IsFast”的“Car”类。或者像“水果”这样带有“ILikeIt”的类。我不想每次都重新编程 WPF 控件,我需要一些方法来绑定(bind)......(哦,我想我刚刚有了一个想法)......但是,是否有任何好的做法来允许泛型类(比如T)只要他们实现某些属性..或包装类?
我不知道,你会如何解决它。与 OnClick 函数的简单绑定(bind)似乎还不够……不确定……顺便说一下,“ 编写 3 个控件”是一个合适的答案 .如果它更简单,请告诉我。
alt text http://img31.imageshack.us/img31/96/listexample.png
最佳答案
我想我明白你在追求什么,这应该让你开始。
我假设您的用户控件有两个 ListView ,一个用于名为“TrueList”的真实项目,另一个用于名为“FalseList”的虚假项目。
从 ItemsCollection 扩展您的用户控件,并将每个 ListView 的 ItemsSource 属性绑定(bind)到父用户控件的 ItemsSource。
将 TrueFilter 和 FalseFilter 属性添加到您的用户控件:
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;
}
}
然后创建一个“IToggle”(或其他更有意义的名称)接口(interface):
public interface IToggle
{
Predicate<object> TrueFilter { get; }
Predicate<object> FalseFilter { get; }
}
然后,为每个自定义类扩展 ObservableCollection,实现“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;
}
接下来,覆盖用户控件上的 ItemsSource 属性:
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;
}
}
最后,在您的事件回调中调用 TrueList.Items.Refresh() 和 FalseList.Items.Refresh() 以在您将项目从 true 切换为 false 时刷新项目 View ,反之亦然。
这个解决方案仍然需要为每个自定义类(true 和 false 过滤器)编写一些实现代码,但它应该将额外的代码保持在最低限度。
或者,如果您为每个自定义类提供一个通用接口(interface),这将是一个更简单的解决方案,例如:
public interface Valid
{
bool IsValid { get; set; }
}
然后,您可以使用一组过滤器(或样式 setter ,或带有转换器的数据绑定(bind))来处理“有效”接口(interface)。您可以使用“Car.IsValid”和“Fruit.IsValid”来代替“Car.IsFast”和“Fruit.ILikeIt”。
关于WPF为多个类创建通用 "Selector Tool",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1002839/