2011-09-20 101 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);