如果将它减少到一个类,问题就很容易了。给定下面的图像,我想创建一个简单的双面控件,根据布尔值将一个列表中的项放入另一个列表中。
编辑:您当然可以点击两个列表中的项目,然后该项目切换到另一个列表。此外,如果我需要更新某些数据库内容,则会调用回调...
我创造了一幅漂亮的照片,让你有点动摇,因为我被卡住了......
世界并不像示例那么简单:您如何为各种类别解决这个问题。
想象一下像“IsFast”这样的“Car”这样的课程。或者像“ILikeIt”这样的“水果”这样的课程。我不想每次重新编程WPF控件,我需要一些方法来绑定...(哦,我想我只是有个想法)......但是,是否有任何好的做法如何允许泛型类(如T)只要它们实现某些属性..或者是一个包装类?
我不知道,你怎么解决它。与OnClick函数的简单绑定似乎还不够......不确定......顺便说一句,“编写3个控件”是一个合适的答案。如果它更简单,请告诉我。
alt text http://img31.imageshack.us/img31/96/listexample.png
答案 0 :(得分:1)
我怎么做?
PickList
的控件,其子类ItemsControl
包含用于挑选单个项目,挑选所有项目,取消所有项目等的命令PickListItem
的类,其中包含IsPicked
属性PickList
的控件模板,以包含两个ListBox
es和一组按钮,用于选择一个,所有等等。该模板将包含一些CollectionViewSource
个用于将那些被挑选的项目(将在右侧)与那些未被采用的项目(将在左侧)隔离。然后您可以像使用任何其他ItemsControl
一样使用此控件,并将其重用于您可能拥有的任何数据类型:
<PickList ItemsSource="{Binding People}">
<PickList.ItemContainerStyle>
<Style TargetType="{x:Type PickListItem}">
<Setter Property="IsPicked" Value="{Binding IsRich}"/>
</Style>
</PickList.ItemContainerStyle>
</PickList>
答案 1 :(得分:1)
我认为我明白你的意思,这应该让你开始。
我假设你的usercontrol有两个listview,一个用于名为“TrueList”的 true 项,另一个用于名为“FalseList”的 false 项。< / p>
从ItemsCollection扩展您的usercontrol,并将每个listview的ItemsSource属性绑定到父usercontrol的ItemsSource。
将 TrueFilter 和 FalseFilter 属性添加到您的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;
}
}
然后创建一个“IToggle”(或其他更有意义的名称)界面:
public interface IToggle
{
Predicate<object> TrueFilter { get; }
Predicate<object> FalseFilter { get; }
}
然后,为每个自定义类扩展ObservableCollection,实现“IToggle”界面:
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时刷新项目视图,反之亦然。
这个解决方案仍然需要为每个自定义类(真假过滤器)编写一些实现代码,但它应该将额外的代码保持在最低限度。
或者,如果您为每个自定义类提供一个通用接口,它将是一个更简单的解决方案,如:
public interface Valid
{
bool IsValid { get; set; }
}
然后,您可以使用一组过滤器(或样式设置器,或使用转换器进行数据绑定)来对抗“有效”接口。而不是“Car.IsFast”和“Fruit.ILikeIt”,你会使用“Car.IsValid”和“Fruit.IsValid”。
答案 2 :(得分:0)
制作用户控件。添加SourceList dep。属性。为回调添加委托属性,为“is in list”过滤器添加委托属性
使用两个ListBox控件(左侧和右侧),使用CollectionViewSource设置两个列表的来源,使用过滤器委托来确定成员资格。