Фильтрация DataGridView, который не имеет привязки данных - PullRequest
6 голосов
/ 10 августа 2009

У меня DGV без привязки к данным (источник данных и т. Д .; строки добавлены вручную). Чтобы отфильтровать его, я делал проверку в цикле и правильно устанавливал свойство visible для строк. Это хорошо работало с меньшими тестовыми наборами, но совершенно не работало с большими. 1k строк фильтруется при 5000 / сек. 10k строк фильтруются со скоростью всего ~ 250 / сек. 50 КБ всего за 40 / сек. Мое предположение о том, что происходит, заключается в том, что каждый раз, когда я меняю видимость строк, DGV перестраивает список отображаемых строк, превращая процесс фильтрации в операцию O (n ^ 2).

Хотя даже 10 тыс. Строк указывают на то, что пользователь злоупотребляет системой; нужно вести учет пользователей с плохим поведением, поэтому мне нужно сделать что-то по-другому. Есть ли более быстрый способ фильтрации большого количества строк, чем то, что я делаю сейчас, без использования привязки данных, или мне нужно прибегнуть к очистке / воссозданию всех строк (для разумных объемов данных это значительно медленнее)?

//psuedocode.  runs slowly if more than a few thousand rows.
foreach (DataGridViewRow row in myDGV)
{
    row.Visible = CalculateFilter(row);
}

Ответы [ 2 ]

8 голосов
/ 15 августа 2009

У меня была эта проблема несколько лет назад (до того, как я узнал об привязках данных), и я нашел сообщение об ошибке в Microsoft, в котором говорилось, что это подтверждено, но проблема, вероятно, не будет исправлена.

Однако есть несколько способов решить эту проблему.

  1. Позволяет добавлять строки в сетку данных, добавлять строки в таблицу данных и связывать их с сеткой данных.

    DataTable table = new DataTable();
    table.Columns.Add("Name", typeof(String));
    table.Columns.Add("...", typeof(String));
    
    foreach (var element in list)
       table.Rows.Add(element.Name, element.Something);
    
    dataGridView1.DataSource = table1;
    table.DefaultView.RowFilter = "Name Like '...'";
    
  2. Создание класса, который наследуется от BindingList и реализует IBindingList. Затем привяжите его к вашему DataGridView.

  3. Установите для DataGridView VirtualMode значение true.

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

И вы должны посмотреть здесь: http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/68c8b93e-d273-4289-b2b0-0e9ea644623a

6 голосов
/ 25 августа 2009

Общая производительность должна значительно улучшиться, если вы временно удалите строки из dataGridView во время фильтрации.

  1. Создание приложения для форм Windows
  2. Перетащите DataGridView и четыре кнопки в форму
  3. Скопируйте и вставьте этот код (не забудьте добавить обработчики событий для событий кнопки)

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        private Stopwatch watch = new Stopwatch();
        private void Form1_Load(object sender, EventArgs e)
        {
            // populate dataGridView
            for (int i = 0; i < 10000; i++)
                dataGridView1.Rows.Add("Column", i+1, 10000 - i);
    
            for (int i = 0; i < 10000; i = i + 2)
                dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Red;
    
        }
    
        // remove filter
        private void button1_Click(object sender, EventArgs e)
        {
            watch.Reset();
            watch.Start();
    
            foreach (DataGridViewRow row in dataGridView1.Rows)
                row.Visible = true;
    
    
            watch.Stop();
            MessageBox.Show(watch.ElapsedMilliseconds.ToString());
        }
    
        // add filter (hide all odd rows)
        private void button2_Click(object sender, EventArgs e)
        {
            watch.Reset();
            watch.Start();
    
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                if (Convert.ToInt32(row.Cells[1].Value) % 2 != 0)
                    row.Visible = false;
            }
    
            watch.Stop();
            MessageBox.Show(watch.ElapsedMilliseconds.ToString());
        }
    
        // remove filter (improved)
        private void button3_Click(object sender, EventArgs e)
        {
            watch.Reset();
            watch.Start();
    
            List<DataGridViewRow> rows = new List<DataGridViewRow>();
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                rows.Add(row);
            }
    
            dataGridView1.Rows.Clear();
    
            foreach (DataGridViewRow row in rows)
                row.Visible = true;
    
            dataGridView1.Rows.AddRange(rows.ToArray());
    
            watch.Stop();
            MessageBox.Show(watch.ElapsedMilliseconds.ToString());
        }
    
        // add filer (improved)
        private void button4_Click(object sender, EventArgs e)
        {
            watch.Reset();
            watch.Start();
    
            List<DataGridViewRow> rows = new List<DataGridViewRow>();
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                rows.Add(row);
            }
    
            dataGridView1.Rows.Clear();
    
            foreach (DataGridViewRow row in rows)
            {
                if (Convert.ToInt32(row.Cells[1].Value) % 2 != 0)
                {
                    row.Visible = false;
                }
            }
    
            dataGridView1.Rows.AddRange(rows.ToArray());
    
            watch.Stop();
            MessageBox.Show(watch.ElapsedMilliseconds.ToString());
        }
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...