Как создать окно загрузки? - PullRequest
1 голос
/ 21 сентября 2010

Хорошо, в моем приложении бывают случаи, когда загрузка DataGridView может занять минуту или две.Я хочу показать GIF в форме без рамки, пока она не достигнет конца функции загрузки.Тем не менее, если я сделаю:

Views.Loading ldw = new Views.Loading();
ldw.Show();
...
ldw.Close();

... он на самом деле никогда не рисует его на экране, и я не вижу его.Если я делаю ShowDialog (), он показывает окно, но никогда не проходит эту строку кода.У меня такое ощущение, что это потому, что это не фоновый работник, или потому что фокус переходит обратно к родителю из-за обработки ... Я не знаю.

Моя форма пустая, добавлена ​​рамка, добавил gif к графическому блоку и сделал FormBorderStyle = none.Мы ценим любую помощь.

Обновление: текущий (нерабочий) код

        private void InitializeBackgroundWorker()
        {
            //Defines the DoWork Event Handler for _backgroundWorker.
            _bgWorkerReports.DoWork += new DoWorkEventHandler(bgWorkerReports_DoWork);
            //Defines the RunWorkCompleted Event Handler for _backgroundWorker.
            _bgWorkerReports.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkerReports_RunWorkerCompleted);
        }

        private void bgWorkerReports_DoWork(object sender, DoWorkEventArgs e)
        {
            ldw.Show();
            try
            {                   
                string strFilter = "";

                if (!_strSearchFilter.Equals(""))
                {
                    strFilter += strFilter.Equals("") ? " " + _strSearchFilter : "  and " + _strSearchFilter;
                }

                if (tvFigure.Nodes.Count > 0)
                {
                    if (_strFigureFilter == "ALL")
                    {
                        strFilter += " " + Constants.GetColumnName("Figure") + " LIKE '%%' ";
                    }
                    else if (!_strFigureFilter.Equals("") && !_strFigureFilter.Equals(tvFigure.TopNode.Name))
                    {
                        if (_strSearchFilter.Equals("") || !cbCurrentFigure.Checked)
                        {
                            strFilter += strFilter.Equals("") ? " " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'" : " and " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'";
                        }
                    }
                }

                if (!_strIndentureFilter.Equals(""))
                {
                    strFilter += strFilter.Equals("") ? " " + _strIndentureFilter : "  and " + _strIndentureFilter;
                }

                if (!_strReportFilter.Equals(""))
                {
                    strFilter += (!strFilter.Equals("") ? " and" : "") + " part_id in (" + _strReportFilter + ")";
                }

                if (strFilter.Length > 0)
                {
                    BindingSource bSource = new BindingSource();
                    bSource.DataSource = _dataController.PopulateDataGrid(_nViewMode, strFilter).Tables[0];

                    //Set DataSource to bindingSource for DataGridView.
                    if (_lstValidationResults.Count > 0)
                    {
                        dgvParts.DataSource = _lstValidationResults;
                        foreach (DataGridViewColumn dc in dgvParts.Columns)
                        {
                            dc.DataPropertyName = "ErrorMessage";
                            dc.Visible = true;
                            dc.SortMode = DataGridViewColumnSortMode.Programmatic;
                            dc.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                        }
                        dgvParts.AutoResizeColumns();
                        return;
                    }
                    else if (!string.IsNullOrEmpty(_strFigureFilter))
                    {
                        dgvParts.DataSource = bSource;
                        dgvParts.Columns[0].Visible = false;
                        dgvParts.Columns["Description"].Resizable = DataGridViewTriState.False;
                        dgvParts.Columns["Description"].Width = 750;
                    }

                    // Automatically resize the visible rows.
                    foreach (DataGridViewColumn col in dgvParts.Columns)
                    {
                        col.SortMode = DataGridViewColumnSortMode.Automatic;
                        if (col.Name != "Description")
                        {
                            dgvParts.AutoResizeColumn(col.Index);
                        }
                    }
                    dgvParts.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;

                    // Hide the ToolTips for all the cells - redisplay if there is a report.
                    dgvParts.ShowCellToolTips = true;

                    // Set the dataGridView control's border.
                    dgvParts.BorderStyle = BorderStyle.Fixed3D;

                    // Get and set the ipb_number to the label.
                    string ipb_number = _dataController.IPBNumber;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void bgWorkerReports_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ldw.Close();
            this.Cursor = Cursors.Default; //Throws error (Cross-thread)

            FormatCells();
            BuildColumnsComboBox();

            int nTotalCount = 0;

            foreach (ListViewItem lvi in listView1.Items)
            {
                int nCount = _lstReportRecords.Where(rr => lvi.Text.Contains(rr.Description)).Count();
                nTotalCount += nCount;
                lvi.Text = (lvi.Text.Contains("(") ? lvi.Text.Substring(0, lvi.Text.IndexOf("(") + 1) : lvi.Text.Trim() + " (") + nCount.ToString() + ")";
            }

            rbAllReports.Text = (rbAllReports.Text.Contains("(") ? rbAllReports.Text.Substring(0, rbAllReports.Text.IndexOf("(") + 1) : rbAllReports.Text + " (") + nTotalCount.ToString() + ")";
            int nTaggedCount = _lstReportRecords.Where(rr => rr.Description.Contains("Tagged")).Count();
            rbTaggedRecords.Text = (rbTaggedRecords.Text.Contains("(") ? rbTaggedRecords.Text.Substring(0, rbTaggedRecords.Text.IndexOf("(") + 1) : rbTaggedRecords.Text + " (") + nTaggedCount.ToString() + ")";
        }

Ответы [ 3 ]

9 голосов
/ 21 сентября 2010

В идеале у вас должно быть два потока: поток GUI и рабочий поток (который может быть BackgroundWorker). Создать и показать окно в потоке графического интерфейса. Обработайте загрузку в событии BackgroundWorker s DoWork. Когда загрузка завершится, вы можете вызвать Close() в окне загрузки из события RunWorkerCompleted и избавиться от него.

LoadWindow loadWindow = new LoadWindow();
loadWindow.TopMost = true;  // make sure it doesn't get created behind other forms
loadWindow.Show();

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    // do your loading here
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // set DataGridView datasource here
    ...

    // close loading window
    loadWindow.Close();
}

Проблема, которая может возникнуть при отображении окна, может быть связана со свойством TopMost, которое должно быть установлено на true. Вы также можете попробовать вызвать BringToFront() в окне загрузки после того, как вы его создали и показали.

1 голос
/ 21 сентября 2010

Да, BackgroundWorker предназначен именно для этого типа целей.Пара вещей, которые нужно добавить:

  1. Не взаимодействовать с пользовательским интерфейсом в событии worker_DoWork, поскольку оно выполняется в фоновом потоке.Установите e.Result, когда вы закончите, что вы можете проверить из события RunWorkerCompleted - или использовать переменную уровня формы.
  2. Пусть любые исключения проваливаются в событии worker_DoWork, и вы увидите их в worker_RunWorkerCompletedсобытие в e.Error.
  3. Если вам нужна возможность отменить загрузку, установите worker.WorkerSupportsCancellation и проверьте e.Cancel, находясь в вашем событии DoWork, тогда вы можете проверить e.Cancelled в вашем событии RunWorkerCompleted.
  4. Вы должны вызвать .Dispose () на BackgroundWorker, когда закончите.
0 голосов
/ 21 сентября 2010

Вам нужно будет запустить код, чтобы заполнить сетку в другом потоке. Что-то вроде:

// Set the picturebox loading state, resize the form etc.
PictureBox.SetLoadingImage();

// Initialize a new thread
Thread t = new Thread(new ThreadStart(() =>
{
    // Fill the gridview here
    GridView1.DataSource = FillWithData();
    GridView1.DataBind();

    // When finished, reset the picturebox on it's own thread
    PictureBox.Invoke((MethodInvoker)(()=> PictureBox.ClearLoadingImage() ));
}));

// Run the thread.
t.Start();
...