Как я могу перебрать DataGridView, созданный в главной форме в BackgroundWorker? - PullRequest
0 голосов
/ 02 сентября 2011

Я хочу перебрать DataGridView, созданный в главной форме в BackgroundWorker для экспорта данных в файл CSV.BackgroundWorker создается в отдельной форме, где прогресс экспорта будет отображаться через индикатор выполнения.Вот код в форме экспорта, который вызывает BackgroundWorker:

private DataGridView exportGrid;

public void ExportCSV(DataGridView mainGrid)
{
    this.exportGrid = mainGrid;

    //Set progress bar maximum
    progressBar1.Maximum = mainGrid.Rows.Count;

    if (backgroundWorker1.IsBusy != true)
    {
        //Start the asynchronous operation
        backgroundWorker1.RunWorkerAsync();
    }

    //Show the form
    this.ShowDialog();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    //Write data rows
    foreach (DataGridViewRow row in exportGrid.Rows)
    {
        //Check if the background worker has been cancelled
        if (worker.CancellationPending == true)
        {
            e.Cancel = true;
            break;
        }
        else
        {
            foreach (DataGridViewCell cell in row.Cells)
            {
                if (cell.Visible)
                {
                    //Do CSV writing here...
                }
            }

            //Report current progress to update UI
            worker.ReportProgress(row.Index + 1);
        }
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    //Update progress bar
    this.progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //Close the form once the background worker is complete
    this.Close();
}

Этот код вызывает следующие ошибки:

  • BindingSource не может быть своим собственным источником данных.Не устанавливайте в свойствах DataSource и DataMember значения, которые ссылаются на BindingSource.
  • Операция между потоками недопустима: элемент управления 'mainGrid' доступен из потока, отличного от потока, в котором он был создан.

Я предполагаю, что это потому, что я обращаюсь к DataGridView в потоке, который его не создал.Каков наилучший способ сделать это?Это вообще возможно?

Обновление:

Причина, по которой я зацикливаюсь на DataGridView вместо источника данных, заключается в том, что пользователи будут изменять порядок столбцов, порядок сортировкии показ / скрытие столбцов сетки, и они хотят, чтобы эти изменения были отражены в экспортированных данных.Есть ли другой способ справиться с этим?

Ответы [ 2 ]

1 голос
/ 02 сентября 2011

Джефф, по моему мнению, вы делаете здесь как минимум две ошибки:

  • Экспорт данных из элемента управления пользовательского интерфейса вместо того, чтобы делать это из источника данных;
  • Попытка получить доступ к элементу управления пользовательского интерфейса из фонового потока;

Я бы просто не пытался получить доступ к элементу управления пользовательского интерфейса (Grid в вашем случае) в форме, которая даже не является формой, в которой объявлен фоновый поток, код будет таким неясным и нечитаемым ...

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

0 голосов
/ 02 сентября 2011

Я сталкивался с этим раньше.Вот как я это сделал.Это взято прямо из проекта, в котором я это делал. Вы должны быть в состоянии получить представление о том, как настроить потоки, чтобы сделать эту работу.Я не включал методы, которые на самом деле пишут CSV-файл, я предполагаю, что ваша основная проблема связана с потоками.И, как сказал Давиде Пирас, вероятно, не очень хорошая идея записывать данные непосредственно из элемента управления.

Событие BackGroundWorker's:

    #region TableWorker Events
    void TableWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        bool done = false;
        GetSwitch();
        ProgressLabel.Visible = true;
        while (!done)
        {
            for (int i = 1; i <= 100; i++)
            {
                Thread.Sleep(100);
                TableWorker.ReportProgress(i);
            }
            done = Export.ExportDataTable(SaveFile, DataTable);
        }
    }

    void TableWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Progress.Style = ProgressBarStyle.Blocks;
        Progress.Value = e.ProgressPercentage;
        ProgressLabel.Text = "Writing File: " + e.ProgressPercentage.ToString() + "% Complete";
    }

    void TableWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Progress.Value = 100;
        ProgressLabel.Visible = false;
        Progress.Visible = false;
        //MessageBox.Show("Export Completed!");
        TableWorker.Dispose();
        ExportButton.Enabled = true;
        this.Close();
    }
    #endregion

Событие, запускающее BackgroundWorker.

    private void EntireTableButton_Click(object sender, EventArgs e)
    {
        dialogResult = Export.SetSaveDialog(SaveFile, ".csv", "csv file (*.csv)|*.csv");

        if (dialogResult == DialogResult.OK)
        {
            TableWorker.RunWorkerAsync();
            this.Hide();
            ProgressLabel.Visible = true;
            ProgressLabel.Text = "Retrieving Data...";
            Progress.Style = ProgressBarStyle.Marquee;
            Progress.Visible = true;
            ExportButton.Enabled = false;

            while (TableWorker.IsBusy)
            {
                Application.DoEvents();
            }
            Progress.Visible = false;
        }
    }

Метод ReportProgress фонового работника позволит вам передавать прогресс в событие ProgressChanged.Сделав это, вы можете обновить индикатор выполнения в другой форме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...