Поиск в listbox с помощью wpf

#c# #wpf #search #listbox

#c# #wpf #Поиск #listbox

Вопрос:

у меня есть listview, привязанный к наблюдаемой коллекции объектов. Здесь объектами являются «вопросы». Я хочу реализовать своего рода поисковую систему. В текстовом поле или что-то в этом роде. Но у меня есть 3 столбца. 1 из описания, 1 из краткого имени и 1 из типа вопроса. Вот код моего listview :

  <ListView IsTextSearchEnabled="True"  TextSearch.TextPath="Description" ScrollViewer.CanContentScroll="True" SelectedItem="{Binding Path=SelectedQuestionDragList, UpdateSourceTrigger=PropertyChanged,Mode=OneWayToSource}" dd:DragDrop.IsDragSource="True" 
  dd:DragDrop.IsDropTarget="False"  Margin="0,34,393,333" Background="#CDC5CBC5" ScrollViewer.VerticalScrollBarVisibility="Visible"
                 dd:DragDrop.DropHandler="{Binding}" Name="listbox1" Height="155"  ItemsSource="{Binding AvailableQuestions}" SelectionChanged="listbox1_SelectionChanged">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Header="Verkorte naam" Width="Auto" DisplayMemberBinding="{Binding Path=ShortName}" />
                        <GridViewColumn Header="Omschrijving" Width="Auto" DisplayMemberBinding="{Binding Path=Description}" />
                        <GridViewColumn Header="Type" Width="Auto" DisplayMemberBinding="{Binding Path=Type}" />
                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
  

Я уже много чего перепробовал. Но я просто хочу сохранить одну простую вещь: текстовое поле, и если вы заполните там несколько букв, программа должна отфильтровать, где существует эта комбинация букв. Кто-нибудь, кто знает простое решение или пример?

Спасибо!

Ответ №1:

Пожалуйста, взгляните на CollectionViewSource

1) Создайте CollectionViewSource:

 private readonly CollectionViewSource viewSource = new CollectionViewSource();
  

2) Укажите свой список в качестве источника:

 viewSource.Source = list;
  

3) Установите свой viewsource в вашем ListView.

4) Когда вы это сделаете, вы можете использовать свойство Filter:

 viewSource.Filter = FilterResults;


private bool FilterResults(object obj)
{
    //match items here with your TextBox value.. obj is an item from the list    
}
  

5) Наконец, поместите метод обновления ViewSource в текст, измененный в текстовом поле вашего фильтра:

  void TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
    viewSource.Refresh();
}
  

Надеюсь, это поможет!

Комментарии:

1. но, я полагаю, все это есть в исходном коде? я пытаюсь поддерживать свой код в чистоте и работает с MVVM .. Есть идея о том, как это сделать?

2. @Ruben, ознакомьтесь с моим ответом о том, как это сделать на вашей виртуальной машине.

3. Работает любой способ.. ключевым моментом здесь является CollectionViewSource , либо путем его создания, либо с использованием значения по умолчанию.

4. ДА. CollectionViewSource отлично подходит для фильтрации, сортировки и т.д., Без необходимости возиться с базовой коллекцией.

Ответ №2:

Вы также можете сделать это в своей ViewModel.

Сначала привяжите свое текстовое поле к свойству в вашей модели представления. Убедитесь, что в вашем XAML вы установили UpdateSourceTrigger значение PropertyChanged , чтобы получать обновления при каждом нажатии клавиши.

 Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
  

В вашей viewmodel настройте свое свойство и свой CollectionView :

     ICollectionView ViewFilter;


    private string _Filter;

    public string Filter
    {
        get { return _Filter; }
        set
        {
            _Filter = value;
            RaisePropertyChanged("Filter");
        }
    }
  

В вашем конструкторе подключите представление и отслеживайте событие propertychanged:

         ViewFilter = CollectionViewSource.GetDefaultView(AvailableQuestion);

        ViewFilter.Filter = delegate(object item)
        {
            AvailableQuestion q = item as AvailableQuestion;
            // Check the value and return true, if it should be in the list
            // false if it should be exclucdd.

        };


        this.PropertyChanged  = ((src, evt) =>
        {
            switch(evt.PropertyName)
            {
                case "Filter":
                    ProjectFilter.Refresh();
                    break;
            }
  

Комментарии:

1. Итак, я должен поместить вторую часть (ViewFilter = CollectionViewSource. GetDefaultView(доступный вопрос);…..) в моем конструкторе моей viewmodel?

2. Да, это нужно поместить в конструктор.

Ответ №3:

Вот пользовательский элемент управления, который я создал, с помощью которого вы можете фильтровать любые ItemsControls, инкапсулирующие любой тип коллекции объектов любого типа. Это лучше, чем оставлять ваш код в чистоте: он заполняет XAML decalrative и совместим с «привязкой» 😉

http://dotnetexplorer.blog.com/2011/04/07/wpf-itemscontrol-generic-staticreal-time-filter-custom-control-presentation/

Вы можете найти исходный код с примером (в следующих публикациях мы углубимся в компонент)

Преимущество заключается в том, что вам не нужно заботиться об управлении представлением коллекции и, таким образом, дополнять свою vewmodel проблемами пользовательского интерфейса (потому что вы должны смотреть правде в глаза: даже если это сделано в view model, фильтрация коллекции в основном касается пользовательского интерфейса, поэтому лучше не находиться в виртуальной машине). По крайней мере, внедрите эту логику в поведение 😉

Вот единственное, что вам нужно, чтобы иметь работающий фильтр в вашем listbox / listview :

 <SmartSearch:SmartSearchRoot x:Name="ss2"    Margin=" 10,0,10,0" >
  <SmartSearch:SmartSearchScope DataControl="{Binding ElementName=YOUR_LISTVIEW_NAME}"  UnderlyingType="{x:Type YOUR_NAMESPACE:YOUR_OBJECT_TYPE}">
     <!-- The list of property on which you want to apply filter -->                    
     <SmartSearch:PropertyFilter FieldName="YOUR_PROPERTY_ONE"  />
     <SmartSearch:PropertyFilter FieldName="YOUR_PROPERTY_TWO" MonitorPropertyChanged=""true"  />
  </SmartSearch:SmartSearchScope>
</SmartSearch:SmartSearchRoot>
  

Комментарии:

1. Я знаю, что это было довольно давно, но ссылка теперь возвращает сообщение 500. Есть ли вероятность, что это размещено где-то еще?