2012-07-19 72 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的方法/屬性。

相關問題