2011-09-20 102 views
0

我想實現一個WPF原型的搜索,我正在使用ListBox和DataTemplate構建它。我試圖設計一種方法來搜索每個項目上幾個TextBlock控件的文本值,然後將可見性設置爲摺疊在任何不包含搜索文本的項目上。如何實現用DataTemplate搜索WPF ListBox?

我認爲我可以做到這一點的一種方式是在ListBox項綁定到的Model上包含屬性,通過ValueConverter將Item的Visibility屬性綁定到該Model屬性,並在搜索期間設置該屬性,但對我來說似乎有點不合適。任何和所有的想法表示讚賞!謝謝!

回答

2

最簡單的答案是使用CollectionViewSource(CVS)來包含您的集合,並將列表框綁定到CVS。 CVS可以執行過濾器,排序和組,而不會影響收集。

代碼隱藏方法

從本質上講,你將有一個事件處理程序,它告訴CVS執行新的過濾器爲代表。礦通常是這個樣子:

Private Sub MyEventHandler() 
    _ShipmentCollectionView.Filter = New Predicate(Of Object)(AddressOf FilterOut) 
End Sub 

Private Function FilterOut(ByVal item As Object) As Boolean 
     Dim MyShipment As Shipment = CType(item, Shipment) 
     If _FilterDelivered And MyShipment.TransitStatus = eTransitStatus.Delivered Then 
      Return False 
     End If 
     If _FilterOverdue And MyShipment.TransitStatus = eTransitStatus.InTransit AndAlso MyShipment.ExpectedDate < Today Then 
      Return False 
     End If 
     If _FilterUnshipped And MyShipment.TransitStatus = eTransitStatus.Unshipped Then 
      Return False 
     End If 
     If SearchString Is Nothing Or SearchString = "" Then 
      Return True 
     Else 

      Return MyShipment.Contains(SearchString) 
     End If 
    End Function 

這樣做是通過FilterOut方法傳遞物品,並返回它們是否符合過濾器。如果他們這樣做,CollectionView(或CVS所屬的部分)會告知UI要顯示哪些項目。

的MVVM方法

(我的收藏夾)

此方法中,所有的過濾器選項控制不同綁定到視圖模型的特性。我最喜歡做的事情是在SearchText屬性設置器中放置_ShipmentCollectionView.Filter = New Predicate(Of Object)(AddressOf FilterOut)行。這樣,每當用戶輸入一個字母(連續過濾)時,就會運行過濾器操作,即假設他們已經正確地進行了綁定(即Text =「{Binding SearchString,UpdateSourceTrigger = PropertyChanged}」)

就我個人而言,推薦MVVM模式,但最簡單的項目除外。它允許用更少的麻煩完成更多更簡潔的工作。

希望有所幫助。

鏈接!

+0

兩個偉大的,很好地解釋選項。這是我在相當一段時間內進行的第一個WPF項目;我忘記了關於CollectionViewSource的所有信息!這些東西非常方便。非常感謝你。 – Patrick

+0

高興,這是有幫助! – CodeWarrior

1

我發現最簡單的方法是應用FilterCollectionViewSource,而不是單獨更新每個項目。

public ObservableCollection<MyObject> Entries { get; set; } 
public CollectionViewSource View { get; set; } 

private string _searchText; 
public string SearchText 
{ 
    get { return _searchText; } 
    set 
    { 
     if (_searchText == value) 
      return; 
     _searchText = value; 
     View.Filter -= ApplySearch; 
     if (!string.IsNullOrWhiteSpace(_searchText)) 
      View.Filter += ApplySearch; 
    } 
} 

public MyClass() 
{ 
    Entries = new ObservableCollection<MyObject>(); 
    View = new CollectionViewSource { Source = Entries }; 
} 

private void ApplySearch(object sender, FilterEventArgs e) 
{ 
     var item = e.Item as MyObject; 
     if (item == null) 
      return; 
     if (item.FirstProperty.IndexOf(SearchText) < 0 && item.SecondProperty.IndexOf(SearchText) < 0) 
      e.Accepted = false; 
} 

注:在這種情況下沒有必要對一個搜索按鈕,但它可能是使用DispatcherTimer設置過濾器之前設置的延遲是一個好主意。

0

使用的CollectionView:

ICollectionView collectionView = CollectionViewSource.GetDefaultView(_source); 
collectionView.Filter = new Predicate<object>(YourFilterFunction);