оптимизируйте обновления DataTable, связанного с DataGridView

await page.$('a') возвращает массив с ElementHandles - это объекты со своим собственным API, специфичным для pupeteer, у них нет обычного DOM API для элементов HTML или узлов DOM. Поэтому вам нужно либо получить атрибуты / свойства в контексте браузера через page.evaluate(), либо использовать довольно сложный API ElementHandles. Это пример с обоими способами:

'use strict';

const puppeteer = require('puppeteer');

(async function main() {
  try {
    const browser = await puppeteer.launch();
    const [page] = await browser.pages();

    await page.goto('https://example.org/');

    // way 1
    const hrefs1 = await page.evaluate(
      () => Array.from(
        document.querySelectorAll('a[href]'),
        a => a.getAttribute('href')
      )
    );

    // way 2
    const elementHandles = await page.$('a');
    const propertyJsHandles = await Promise.all(
      elementHandles.map(handle => handle.getProperty('href'))
    );
    const hrefs2 = await Promise.all(
      propertyJsHandles.map(handle => handle.jsonValue())
    );

    console.log(hrefs1, hrefs2);

    await browser.close();
  } catch (err) {
    console.error(err);
  }
})();
9
задан Will Rogers 20 March 2009 в 19:18
поделиться

4 ответа

Вы рассмотрели разъединение dataGrid или bindingSource при заполнении таблицы и повторном подключении впоследствии? Это могло бы выглядеть немного ужасным, но это должно быть намного быстрее.

4
ответ дан 4 December 2019 в 13:05
поделиться

Можно попытаться использовать метод Слияния на DataTable. Я попытаюсь создать простое демонстрационное приложение и отправить его здесь, но идея проста. Когда Вы захотите обновить Сетку, запросите результаты в новый DataTable и затем объедините старую таблицу с новой таблицей. Пока обе таблицы имеют первичные ключи (можно создать их их, я - память, если они не возвращаются из DB), затем, это должно отследить изменения и обновить DataGridView беспрепятственно. Это также имеет преимущество не потери пользовательского места на сетке.

Хорошо, вот образец. Я создаю форму с двумя кнопками и одним dataGridView. При щелчке button1 я заполняю основную таблицу с некоторыми данными и связываю сетку с ним. Затем при втором щелчке я составляю другую таблицу с той же схемой. Добавьте данные к нему (некоторые, которые имеют тот же первичный ключ и некоторых, которые имеют новые). Затем они объединяют их назад с исходной таблицей. Это обновляет сетку как ожидалось.

    public partial class Form1 : Form
    {
        private DataTable mainTable;
        public Form1()
        {
            InitializeComponent();
            this.mainTable = this.CreateTestTable();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            for (int i = 1; i <= 10; i++)
            {
                this.mainTable.Rows.Add(String.Format("Person{0}", i), i * i);
            }

            this.dataGridView1.DataSource = this.mainTable;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            DataTable newTable = this.CreateTestTable();
            for (int i = 1; i <= 15; i++)
            {
                newTable.Rows.Add(String.Format("Person{0}", i), i + i);
            }
            this.mainTable.Merge(newTable);
        }

        private DataTable CreateTestTable()
        {
            var result = new DataTable();
            result.Columns.Add("Name");
            result.Columns.Add("Age", typeof(int));
            result.PrimaryKey = new DataColumn[] { result.Columns["Name"] };

            return result;

        }
    }
6
ответ дан 4 December 2019 в 13:05
поделиться

Если Вы используете a BindingSource для сложной привязки данных важно понять это SuspendBinding и ResumeBinding только приостановите и продолжите связывать для текущего объекта. Это позволяет Вам отключить привязку для текущего объекта и изменить набор его свойств без любого из отдельных изменений в свойстве, выставляемом к связанному элементу управления. (Это не объяснено в документации для BindingSource, где это было бы полезно, о нет: это находится в документации для CurrencyManager.)

Любые изменения, которые Вы вносите в другие объекты в списке, т.е. всем кроме текущего объекта, повышают ListChanged событие. При отключении этих событий BindingSource прекращает говорить связанный элемент управления об изменениях в списке, пока Вы не повторно включаете им. Это имеет результат, который Вы видели: Вы добавляете все свои строки к базовому DataTable, но так как Вы повернулись ListChanged события прочь, BindingSource не говорит DataGridView о них, и таким образом, DataGridView остается пустым.

Надлежащее решение состоит в том, чтобы звонить ResetBindings, который вызывает BindingSource обновить все средства управления, связанные с ним, с помощью текущих значений в его связанном списке.

Какие исключения - Вы добирающийся после вызова ResetBindings? Поскольку это работает просто великолепно для меня, добавляю ли я, редактирую, удаляю или удаляю строки из базового DataTable.

3
ответ дан 4 December 2019 в 13:05
поделиться

Я столкнулся с похожей проблемой. Вот решение, которое еще проще (хотя и менее элегантно).

Я обнаружил, что это:

dataGridView.DataSource = null;
dataTable.BeginLoadData();
foreach(DataRow row in dataTable.Rows){
    //modify row
}
dataTable.EndLoadData();
dataGridView.DataSource = dataTable;

...намного быстрее, чем это:

dataTable.BeginLoadData();
foreach(DataRow row in dataTable.Rows){
    //modify row
}
dataTable.EndLoadData();

Cheers--DC

2
ответ дан 4 December 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: