我想实现搜索我正在构建的WPF原型,我正在使用带有DataTemplate的ListBox。我正在尝试设计一种方法来搜索每个项目上的几个TextBlock控件的文本值,然后在不包含搜索文本的任何项目上设置Visibility to Collapsed。
我认为我可以这样做的一种方法是在模型中包含一个属性,ListBox项目绑定到该模型,通过ValueConverter将Item的Visibility属性绑定到该Model属性,并在搜索期间设置该属性,但是对我来说似乎很笨拙。任何和所有的想法都表示赞赏!谢谢!
答案 0 :(得分: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要显示哪些项目。
(我最喜欢的)
此方法的不同之处在于,所有过滤器选项控件都绑定到ViewModel中的属性。我最喜欢这样做的是在SearchText属性设置器中放置_ShipmentCollectionView.Filter = New Predicate(Of Object)(AddressOf FilterOut)行。这样,每次用户键入一个字母(连续过滤)时都会运行过滤操作,即假设它们具有正确的绑定(即Text =“{Binding SearchString,UpdateSourceTrigger = PropertyChanged}”)
我个人建议除了最简单的项目之外的所有项目的MVVM模式。它可以让你更轻松地完成更多整洁的工作。
希望有所帮助。
答案 1 :(得分:1)
我发现最简单的方法是将Filter应用于CollectionViewSource,而不是单独更新每个项目。
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设置延迟可能是个好主意。
答案 2 :(得分:0)
使用CollectionView:
ICollectionView collectionView = CollectionViewSource.GetDefaultView(_source);
collectionView.Filter = new Predicate<object>(YourFilterFunction);