WPF创建通用的;选择工具";对于多个类

WPF创建通用的;选择工具";对于多个类,wpf,list,Wpf,List,如果你把它简化成一个类,这个问题就相当容易了。给出下图,我想创建一个简单的双面控件,它根据布尔值将一个列表中的项目放入另一个列表中 编辑:您当然可以单击两个列表中的项目,然后该项目切换到另一个列表。此外,还会调用一个回调,以防我需要更新一些数据库内容 我创造了一张很好的照片来感动你,因为我被卡住了 世界并不像下面的例子那样简单:对于不同的类,您将如何解决这个问题。 想象一个像“Car”这样带有“IsFast”的类。或者像“水果”这样的带有“ILikeIt”的类。我不想每次都重新编程WPF控件,我

如果你把它简化成一个类,这个问题就相当容易了。给出下图,我想创建一个简单的双面控件,它根据布尔值将一个列表中的项目放入另一个列表中

编辑:您当然可以单击两个列表中的项目,然后该项目切换到另一个列表。此外,还会调用一个回调,以防我需要更新一些数据库内容

我创造了一张很好的照片来感动你,因为我被卡住了

世界并不像下面的例子那样简单:对于不同的类,您将如何解决这个问题。

想象一个像“Car”这样带有“IsFast”的类。或者像“水果”这样的带有“ILikeIt”的类。我不想每次都重新编程WPF控件,我需要一些方法来绑定。。。(哦,我想我刚刚有了一个想法)。。。但是,如果泛型类(比如T)实现了某些属性,那么还有什么好的做法可以允许它们呢。。还是包装类

我不知道,你会怎么解决它。使用OnClick函数的简单绑定似乎不够。。。不确定。。。顺便说一下,“编写3个控件”是一个合适的答案。如果更简单,就告诉我


创建一个用户控件。添加SourceList dep.属性。为回调添加委托属性,为“在列表中”筛选器添加委托属性

使用两个ListBox控件(左和右),用于设置两个列表的源,使用筛选器委托确定成员身份。

我该怎么做

  • 创建名为
    PickList
    的控件,该控件将
    ItemsControl
    子类化,并包含用于拾取单个项目、拾取所有项目、取消拾取所有项目等的命令
  • 创建一个名为
    PickListItem
    的类,该类具有
    IsPicked
    属性
  • 定义
    PickList
    的控制模板,以包括两个
    ListBox
    es和一组用于选择一个、所有等的按钮。该模板将包括两个
    CollectionViewSource
    s,用于将拾取的项目(位于右侧)与未拾取的项目(位于左侧)分开
然后,您可以像使用任何其他
ItemsControl
一样使用此控件,并将其重新用于您可能拥有的任何数据类型:

<PickList ItemsSource="{Binding People}">
    <PickList.ItemContainerStyle>
        <Style TargetType="{x:Type PickListItem}">
            <Setter Property="IsPicked" Value="{Binding IsRich}"/>
        </Style>
    </PickList.ItemContainerStyle>
</PickList>

我想我知道你在追求什么,这应该让你开始

我假设您的usercontrol有两个ListView,一个用于名为“TrueList”的真实项,另一个用于名为“FalseList”的虚假项

从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;
        }
    }
最后,在事件回调上调用TrueList.Items.Refresh()和FalseList.Items.Refresh(),以便在将项目从true切换到false时刷新项目视图,反之亦然

这个解决方案仍然需要为每个自定义类(true和false过滤器)编写一些实现代码,但它应该将额外的代码保持在最低限度

或者,如果您为每个自定义类提供一个公共接口,这将是一个简单得多的解决方案,例如:

public interface Valid
{
   bool IsValid { get; set; }
}

然后可以使用一组过滤器(或样式设置器,或使用转换器进行数据绑定)来处理“有效”接口。用“Car.IsFast”和“Fruit.ILikeIt”代替“Car.IsValid”和“Fruit.IsValid”。

好的,谢谢。。我认为关键字是**委托属性**,如果我取得显著进展,将对此进行研究并发表文章……您可以查看CollectionViewSource类,了解您的委托应该是什么样的。我认为这是一种方法。。我将按照您描述的方式实现它,并检查是否有任何不清楚的地方,然后带着反馈返回..PickListItem将从哪个类继承?DependencyObject,ContentControl,…?ContentControl-就像ListBoxItem,例如。好的,我正在尝试你的方法,因为它似乎是建议的方法,与WPF的设计工作方式最为一致。然而,我遇到了麻烦,任何关于如何实现其余部分的澄清或额外细节都会有所帮助。
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;
    }
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;
   }
}
public interface Valid
{
   bool IsValid { get; set; }
}