2012-07-19 53 views
1

我必须在我的应用程序中实现“全局”搜索/过滤功能。每个包含信息列表的窗口(无论是DataGrid还是某个列表的其他实现)都必须有一个搜索框,并且如果用户在搜索框中输入文本,它将通过搜索任何内容来过滤该列表。我只想实现一次搜索逻辑。如何实现可用于不同类型对象的功能?

大多数情况下,这不一定会太困难。原因是大多数包含列表的窗口将基于相同的数据类型。这些都是ViewModels,每个ViewModel扩展ViewModelBase,ViewModelBase包含我将要搜索的数据。

一个基本的例子:

public class ZoneVm : ViewModelBase 
{ 
    // Zone specific functionality 
} 

public class UserVm : ViewModelBase 
{ 
    // User specific functionality 
} 

public class ViewModelBase : INotifyPropertyChanged 
{ 
    public string Name { get; set; } 
    public int Value { get; set; } 

    // The handy thing about the common view model base is that 
    // I can contain the model binding in a single place 

    // It will be easy to search List<ZoneVm> and List<UserVm> because 
    // they are both effectively List<ViewModelBase>. 
} 

的困难在于,我要寻找离群对象。某些窗口包含不需要扩展ViewModelBase的对象列表,因此我不会有这个可预测的属性列表进行搜索,例如,

public class PanelData // doesn't implement ViewModelBase :-(
{ 
    public int SerialNumber { get; set; } 
    public Customer Customer { get; set; } 

    // other properties that I'll have to search/filter on 
} 

是否有这种任务的“最佳实践”方法?有没有解决这个问题的设计模式?我该如何处理搜索/过滤2个(可能更多)不同种类的列表?

+0

你有没有考虑过使用反射?您可以使用Attribute标记这些属性,并在应用程序加载时解析它们,并为这些搜索/可过滤属性保存缓存的Accessors列表。 – dowhilefor 2012-07-19 08:55:54

+0

Hi @dowhilefor(nice name,btw :-)),我没有考虑反思,但现在认为它可能是有用的。我可以迭代每个属性(不管它是什么),并将它的'ToString()'值与搜索项进行比较。随着我进一步探索,我会记住这一点。谢谢。 – DaveDev 2012-07-19 11:01:33

回答

0

我想你不想让每个数据都有一个共同的可搜索成员? (这可能是通过使用与此抽象成员共同的IData接口处理,如Ofer所说)

我会让他们在一个可查询集合中并在抽象fasion中实现搜索(请自己填写空格):

class MySearchableDataListBase<T> : INotifyPropertyChanged 
{ 
    List<T> _list = new List<T>(); 
    string _currentFilterString = ""; 

    abstract bool FilterItemPredicate(T item, string query); 

    public abstract IEnumerable<T> FilteredItems 
    { 
     get { 
     return _list.Where(i => FilterItemPredicate(i, _currentFilterString)).ToArray(); 
     } 
    } 

    public string FilterQuery 
    { 
     get { return _currentFilterString; } 
     set { 
     if (value != _currentFilterString) 
     { 
      _currentFilterString = value; 
      OnPropertyChanged("FilterQuery"); 
      OnPropertyChanged("FilteredItems"); 
     } 
     } 
    } 
} 

然后,您可以将其用作数据的集合,并为过滤/搜索提供命令和属性。

+0

这并不完全是答案,但它提供了一个很好的框架来开始。谢谢。 – DaveDev 2012-07-24 07:44:45

0

我的建议是创建一个接口而不是基类,即IViewModelBase。该接口可以是空的。另外,创建你的基类,但它只针对某些对象(这也是抽象的)。

public interface IViewModelBase : INotifyPropertyChanged 
{ 
} 

public abstract class Vm : IViewModelBase 
{ 
     public string Name { get; set; } 
     public int Value { get; set; } 
     public event PropertyChangedEventHandler PropertyChanged; 
} 

public class ZoneVm : Vm 
{ 
    // Zone specific functionality 
} 

public class UserVm : Vm 
{ 
    // User specific functionality 
} 

public class PanelData : IViewModelBase 
{ 
    public int SerialNumber { get; set; } 
    public Customer Customer { get; set; } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 
0

你可能想看看混入:re - mix

它可以让你在对象混合功能(这是一个有点像多继承)。
然后,您可以提供接口实现,并且具有继承Window AND的类,并且具有可通过接口使用的ViewModelBase的方法/属性。

相关问题