Подтвердить что ты не робот

Фильтрация DataGrid в WPF

Я загружаю списки объектов в datagrid с помощью этого:

dataGrid1.Items.Add(model);

model становятся данными из базы данных. Он имеет Id(int), Name(string) и Text(string)

В моем datagrid я показываю только имя model. Как я могу отфильтровать datagrid сейчас, когда я ввожу что-то в текстовое поле?

Я был на этой странице: http://msdn.microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspx, но я не понимаю код оттуда, и я не могу объяснить, как я должен транспонировать что для моей проблемы.

4b9b3361

Ответ 1

существует несколько способов фильтрации Collection

предположим, что это ваш класс предметов

public class Model
{
    public string Name
    {
        get;
        set;
    }
}

и ваша коллекция выглядит как

       var ObColl = new ObservableCollection<Model>();

        ObColl.Add(new Model() { Name = "John" });
        ObColl.Add(new Model() { Name = "Karl" });
        ObColl.Add(new Model() { Name = "Max" });
        ObColl.Add(new Model() { Name = "Mary" });

Способ 1 (предикат):

    public MainWindow()
    {
        InitializeComponent();

        // Collection which will take your ObservableCollection
        var _itemSourceList = new CollectionViewSource() { Source = ObColl };

        // ICollectionView the View/UI part 
        ICollectionView Itemlist = _itemSourceList.View;

        // your Filter
        var yourCostumFilter= new Predicate<object>(item => ((Model)item).Name.Contains("Max"));

        //now we add our Filter
        Itemlist.Filter = yourCostumFilter;

        dataGrid1.ItemsSource = Itemlist;
    }

Способ 2 (FilterEventHandler):

    public MainWindow()
    {
        InitializeComponent();

        // Collection which will take your Filter
        var _itemSourceList = new CollectionViewSource() { Source = ObColl };

       //now we add our Filter
       _itemSourceList.Filter += new FilterEventHandler(yourFilter);

        // ICollectionView the View/UI part 
        ICollectionView Itemlist = _itemSourceList.View;

        dataGrid1.ItemsSource = Itemlist;
    }

    private void yourFilter(object sender, FilterEventArgs e)
    {
        var obj = e.Item as Model;
        if (obj != null)
        {
            if (obj.Name.Contains("Max"))
                e.Accepted = true;
            else
                e.Accepted = false;
        }
    }

расширенная информация в пути 1

если вам нужно несколько условий или какой-либо сложный фильтр, вы можете добавить метод к вашему Predicat

    // your Filter
    var yourComplexFilter= new Predicate<object>(ComplexFilter);

    private bool ComplexFilter(object obj)
    {
        //your logic
    }

Ответ 2

Это простая реализация использования свойства фильтра ICollectionView. Предположим, что ваш XAML содержит следующее:

<TextBox x:Name="SearchTextBox" />
<Button x:Name="SearchButton"
        Content="Search"
        Click="SearchButton_OnClick"
        Grid.Row="1" />
<DataGrid x:Name="MyDataGrid"
          Grid.Row="2">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Lorem ipsum column"
                            Binding="{Binding}" />
    </DataGrid.Columns>
</DataGrid>

Затем в конструкторе вы можете получить представление по умолчанию для своих данных, где вы можете установить предикат фильтра, который будет выполнен для каждого элемента вашей коллекции. CollectionView не будет знать, когда он должен обновить коллекцию, поэтому вам нужно позвонить Refresh, когда пользователь нажимает кнопку поиска.

private ICollectionView defaultView;

public MainWindow()
{
    InitializeComponent();

    string[] items = new string[]
    {
        "Asdf",
        "qwer",
        "sdfg",
        "wert",
    };

    this.defaultView = CollectionViewSource.GetDefaultView(items);
    this.defaultView.Filter =
        w => ((string)w).Contains(SearchTextBox.Text);

    MyDataGrid.ItemsSource = this.defaultView;
}

private void SearchButton_OnClick(object sender, RoutedEventArgs e)
{
    this.defaultView.Refresh();
}

На этом URL-адресе вы можете найти более подробное описание CollectionViews: http://wpftutorial.net/DataViews.html

Ответ 3

@WiiMaxx, не может комментировать, так как недостаточно rep. Я был бы немного осторожен в отношении прямых бросков. Они могут быть медленными для одной вещи, а для другой, если тот же фильтр был применен к сетке, содержащей различные данные сложного типа, у вас было бы InvalidCastException.

// your Filter
    var yourCostumFilter= new Predicate<object>(item =>
    {
        item = item as Model;
        return item == null || item.Name.Contains("Max");
    });

Это не сломает вам datagrid и не будет фильтровать результаты, если сбой выполняется. Меньшее влияние на ваших пользователей, если вы ошиблись в коде. Кроме того, фильтр будет быстрее из-за того, что оператор "как" не делает никакого явного принуждения типа, поскольку операция прямого литья будет.

Ответ 4

взгляните на DataBinding → в вашем случае не добавляйте элементы в свою сетку, а установите itemssource

<Datagrid ItemsSource="{Binding MyCollectionOfModels}" />

или

dataGrid1.ItemsSource = this._myCollectionOfModels;

и если вы хотите, чтобы какая-то фильтрация, сортировка, группировка смотрели на CollectionView

Ответ 5

Вы можете использовать фильтр dataview, чтобы отфильтровать строки datagrid.

            DataView dv = datatable.DefaultView;

            StringBuilder sb = new StringBuilder();
            foreach (DataColumn column in dv.Table.Columns)
            {
                sb.AppendFormat("[{0}] Like '%{1}%' OR ", column.ColumnName, "FilterString");
            }
            sb.Remove(sb.Length - 3, 3);
            dv.RowFilter = sb.ToString();
            dgvReports.ItemsSource = dv;
            dgvReports.Items.Refresh();

Если "datatable" - это источник данных, предоставленный вашему datagrid и использующий построитель строк, вы создаете запрос фильтра, где "Filter String" - это текст, который вы хотите найти в вашем datagrid, и установите его в dataview и, наконец, установите dataview как источник данных к вашему datagrid и обновите его.