it-swarm.com.ru

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

Я загружаю списки объектов в сетку данных с этим:

dataGrid1.Items.Add(model);

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

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

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

10
Karl_Schuhmann

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

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

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
    }
32
WiiMaxx

Это простая реализация использования свойства Filter объекта 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();
}

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

5
Loránd Biró

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

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

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

3
steve

Вы можете использовать фильтр dataview для фильтрации строк сетки данных.

            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» - это источник данных, предоставленный вашей сетке данных, и используя построитель строк, вы строите запрос фильтра, где «Filter String» - это текст, который вы хотите искать в вашей сетке данных, и устанавливаете его как dataview, и, наконец, устанавливаете dataview как источник данных для вашей сетки данных. и обнови это.

0
Joee

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

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

или же 

dataGrid1.ItemsSource = this._myCollectionOfModels;

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

0
blindmeis