我必须在我的应用程序中实现'全局'搜索/过滤功能。每个包含信息列表的窗口,无论是DataGrid还是列表的其他实现,都必须有一个搜索框,如果用户在搜索框中输入文本,它将按搜索的内容过滤该列表。我只想实现一次搜索逻辑。
在大多数情况下,这不一定太难。原因是大多数包含列表的窗口将基于相同的数据类型。这些都是ViewModel,每个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 :(得分: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;
}
答案 1 :(得分:0)
我认为您不希望每个数据都有一个共同的可搜索成员? (这可以通过使用与这个抽象成员的公共IData接口来进行处理,如Ofer所说)
我会将它们放在可查询的集合中并以抽象的方式实现搜索(请自行填写空白):
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");
}
}
}
}
然后,您可以将其用作数据的集合,并为过滤/搜索提供命令和属性。
答案 2 :(得分:0)