繁体   English   中英

如何使用DataTemplate实现对WPF ListBox的搜索?

[英]How can I implement search for a WPF ListBox with DataTemplate?

我想实现对正在构建的WPF原型的搜索,在该原型中,我将使用带有DataTemplate的ListBox。 我正在尝试设计一种方法来搜索每个项目上几个TextBlock控件的文本值,然后在不包含搜索文本的任何项目上将“可见性”设置为“折叠”。

我认为可以做到这一点的一种方法是在Model上包含一个将ListBox Items绑定到的属性,通过ValueConverter将Item的Visibility属性绑定到该Model属性,并在搜索过程中设置该属性,但似乎有点对我来说很糊涂。 任何和所有的想法表示赞赏! 谢谢!

最简单的答案是使用CollectionViewSource(CVS)来包含您的集合,并将列表框绑定到CVS。 CVS可以执行过滤器,排序和分组,而不会影响集合。

CODEBEHIND方法

本质上,您将拥有一个事件处理程序,该事件处理程序告诉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方法

(我的最爱)

此方法的不同之处在于,所有过滤器选项控件都绑定到ViewModel中的属性。 我最喜欢做的是将_ShipmentCollectionView.Filter = New Predicate(Of Object)(AddressOf FilterOut)行放在SearchText属性设置器中。 这样,每次用户键入字母(假定他们已正确进行绑定)(即Text =“ {Binding SearchString,UpdateSourceTrigger = PropertyChanged}”)时,都会运行筛选器操作(连续筛选)

我个人建议除了最简单的项目外,将MVVM模式用于所有项目。 它允许完成许多更整洁的工作,而麻烦却少得多。

希望能有所帮助。

链接!

我发现最简单的方法是将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设置延迟可能是个好主意。

使用CollectionView:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM