Фильтрация строк DataGridView, когда DataSource привязан к коллекции сущностей EF5

У меня есть DataGridView, который привязан к BindingList.

private void InitGrid()
{
    Ctx.MyEntitySet.Load();
    dataGridView1.DataSource = Ctx.MyEntitySet.Local.ToBindingList();
    dataGridView1.Columns["Id"].Visible = false;
    dataGridView1.Columns["UnwantedCol1"].Visible = false;
    dataGridView1.Columns["UnwantedCol2"].Visible = false;
    dataGridView1.Columns["UnwantedCol3"].Visible = false;
}

и фильтрующий TextBox с обработкой события TextChanged следующим образом

private void textBoxFilter_TextChanged(object sender, EventArgs e)
{
    try
    {
        string filter = textBoxFilter.Text.Trim();
        ((DataView)dataGridView1.DataSource).RowFilter = filter;
        textBoxFilter.BackColor = SystemColors.AppWorkspace;
    }
    catch (Exception)
    {
        textBoxFilter.BackColor = Color.Red;
        ToolTip tip = new ToolTip();
        tip.SetToolTip(textBoxFilter, ex.Message);
    }
}

Я запускаю код, данные отображаются правильно, но когда я пытаюсь ввести что-то вроде ColumnName like '%sometext%' в текстовое поле моего фильтра, я получаю исключение, говорящее, что я не могу привести «System.Data.Entity.Internal.ObservableBackedBindingList`1[MyEntity ]» на «System.Data.DataView».

Может ли кто-нибудь дать мне указатель?

Спасибо, Ф.

РЕШЕНО:

Добавлен общий метод расширения

public static class LocalExtensions
{
    public static IEnumerable<T> Filter<T>(this IEnumerable<T> list, Func<T, bool> filterParam)
    {
        return list.Where(filterParam);
    }
}

И измененный обработчик события TextChanged следующим образом:

private void textBoxFilter_TextChanged(object sender, EventArgs e)
{
    try
    {
        string filter = textBoxFilter.Text.Trim();

        dataGridView1.DataSource =
            Ctx.MyEntitySet.Local
            .Filter(x =>
                x.EntityPropertyToSearchIn1.ToUpper().Contains(filter.ToUpper()) ||
                x.EntityPropertyToSearchIn2.ToUpper().Contains(filter.ToUpper())
            ).ToList();

        textBoxFilter.BackColor = SystemColors.AppWorkspace;
    }
    catch (Exception)
    {
        textBoxFilter.BackColor = Color.Red;
        ToolTip tip = new ToolTip();
        tip.SetToolTip(textBoxFilter, ex.Message);
    }
}

person silentman.it    schedule 31.10.2012    source источник
comment
Во-первых, я могу сказать вам, что типы несовместимы. Вы привязываете BindingList для использования в качестве DataView (тип DataGridView), что не разрешено.   -  person digaomatias    schedule 31.10.2012


Ответы (3)


По сути, вы не можете поместить BindingList прямо в ваш DataGridView. Вам потребуется определить BindingSource и назначьте BindingList этому BindingSource. Попробуйте это, чтобы увидеть, работает ли это:

Ctx.MyEntitySet.Load();
BindingSource yourBS = new BindingSource();
yourBS.DataSource = Ctx.MyEntitySet.Local.ToBindingList();

dataGridView1.DataSource = yourBS;
dataGridView1.Columns["Id"].Visible = false;
dataGridView1.Columns["UnwantedCol1"].Visible = false;
dataGridView1.Columns["UnwantedCol2"].Visible = false;
dataGridView1.Columns["UnwantedCol3"].Visible = false;

Надеюсь это работает. :)

С уважением.

person digaomatias    schedule 31.10.2012
comment
Привязка уже работала. Фильтрация данных не работает. Если я применю ваше редактирование, я получу то же исключение в обработчике событий TextChanged (с BindingSource вместо BindingList) - person silentman.it; 31.10.2012

Вам нужно будет создать новый BindingList, который будет отфильтрован. Легко сделать с LINQ. См. Фильтрация списка привязок

try
{
    string filter = textBoxFilter.Text.Trim();
    dataGridView1.DataSource = new BindingList<YOUR_ENTITY>(Ctx.MyEntitySet.Local.ToBindingList().Where(x => x.EntityPropertyToSearchIn1.ToUpper().Contains(filter)).ToList<YOUR_ENTITY>());
    textBoxFilter.BackColor = SystemColors.AppWorkspace;
}
person elady    schedule 08.04.2014

А вот эквивалент VB для метода расширения:

Imports System.Runtime.CompilerServices

Module LocalExtensions

    <Extension()> _
    Public Function Filter(Of T)(list As IEnumerable(Of T), filterParam As Func(Of T, Boolean)) As IEnumerable(Of T)
        Return list.Where(filterParam)
    End Function

End Module
person Leigh    schedule 29.01.2015