C#WPF在Datagrid填充期间冻结Progressbar

时间:2017-04-11 14:28:41

标签: c# wpf datagrid user-controls progress-bar

我的查询速度很慢。跑步后需要一段时间。我想在线程中显示进度条。我尝试使用backgroundworker。

我正在使用usercontrol,这是我的面板儿童。下图是主页。当我点击第1页时,我的dockpanel将有page_1 usercontrol。

Mainwindow

    private void button_Click(object sender, RoutedEventArgs e)
    {
        page1 pg = new page1();
        Container_Panel.Children.Add(pg);
    }

我正在尝试在打开page1 usercontrol时显示未确定的进度条。我使用这些代码。

    private BackgroundWorker bw = new BackgroundWorker();

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
       Application.Current.Dispatcher.Invoke(new Action(() =>
       {
          populate();
       }));
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        prg2.Visibility = Visibility.Hidden;    
    }

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                bw.WorkerReportsProgress = true;
                bw.DoWork += bw_DoWork;
                //bw.ProgressChanged += bw_ProgressChanged;
                bw.RunWorkerCompleted += bw_RunWorkerCompleted;
                bw.RunWorkerAsync();
                prg2.Visibility = Visibility.Visible;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

以下数据网格代码的方法

private void populate ()
{
            using (SqlConnection con= new SqlConnection(connectionstring))
            {
                con.Open();
                DataTable dt = new DataTable();
                SqlCommand cmd= new SqlCommand("Select ...", con);
                cmd.CommandTimeout = 0;
                SqlDataAdapter _dadapt= new SqlDataAdapter();
                _dadapt.Fill(dt); 
                con.Close();
                dataGrid1.itemsSource = dt.DefaultView;
            }
}

代码正常工作,我可以看到prg2(进度条)变得可见。但是直到查询结束才冻结。之后,其他进程隐藏正在工作,进度条隐藏。但我想在查询过程中使进度条不确定。

或者我可以在使用clickwindows按钮的containerpanel之外创建一个进度条。

我正在尝试解决这个问题,我尝试了太多应用但无法解决。

5 个答案:

答案 0 :(得分:1)

试试这个

private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        populate();
    }

private void populate ()
{
            using (SqlConnection con= new SqlConnection(connectionstring))
            {
                con.Open();
                DataTable dt = new DataTable();
                SqlCommand cmd= new SqlCommand("Select ...", con);
                cmd.CommandTimeout = 0;
                SqlDataAdapter _dadapt= new SqlDataAdapter();
                _dadapt.Fill(dt); 
                con.Close();
                bw.ReportProgress(90,dt.DefaultView);
            }
}

实施报告进度事件

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
       if(e.ProgressPercentage == 90)
       {
              dataGrid1.itemsSource = (DataView)e.UserState;// don't remember if it's the same property but there's a property check
       }
}

答案 1 :(得分:1)

您应该使用任务,因为不需要后台工作程序。此外,您还需要使用async / await,以便在不影响UI的情况下正确更新Visibility。

另请注意,不需要con.Close(),因为它已经包含在using语句中。

private async void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    try
    {
        prg2.Visibility = Visibility.Visible;

        dataGrid1.itemsSource = await GetDataAsync();

        prg2.Visibility = Visibility.Hidden; 
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private Task<DataView> GetDataAsync()
{
    return Task.Run(()=>
    {
        using (var con = new SqlConnection(connectionstring))
        {
            con.Open();

            var dt = new DataTable();
            var cmd= new SqlCommand("Select ...", con);
            cmd.CommandTimeout = 0;

            var dadapt = new SqlDataAdapter();
            dadapt.Fill(dt); 

            return dt.DefaultView;  
        }
    });
}

答案 2 :(得分:0)

 private BackgroundWorker bw = new BackgroundWorker();

 private void bw_DoWork(object sender, DoWorkEventArgs e)
{

      populate();

}

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    prg2.Visibility = Visibility.Hidden;    
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        try
        {
            bw.WorkerReportsProgress = true;
            bw.DoWork += bw_DoWork;
            //bw.ProgressChanged += bw_ProgressChanged;
            bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            prg2.Visibility = Visibility.Visible;
            bw.RunWorkerAsync();

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }


 private void populate ()
 {
        using (SqlConnection con= new SqlConnection(connectionstring))
        {
            con.Open();
            DataTable dt = new DataTable();
            SqlCommand cmd= new SqlCommand("Select ...", con);
            cmd.CommandTimeout = 0;
            SqlDataAdapter _dadapt= new SqlDataAdapter();
            _dadapt.Fill(dt); 
            con.Close();
            Application.Current.Dispatcher.Invoke(new Action  (() =>
                {
                dataGrid1.itemsSource = dt.DefaultView;
                }));
        }
  }

答案 3 :(得分:0)

您可以使用nuget中的Xceed BusyIndi​​cator控件,输入

Install-Package Extended.Wpf.Toolkit 
在程序包管理器控制台上

。在View参考中添加控件

<wpfex:BusyIndicator IsBusy="{Binding IsBusy}" DisplayAfter="0" BusyContent="{Binding IsBusyMessage}"  />

并将其绑定到您的模型视图,无论如何您必须异步执行查询

答案 4 :(得分:0)

我会尝试这样的事情

    // ##############################################################################################################################
    // Properties
    // ##############################################################################################################################

    private BackgroundWorker _BackgroundWorker = new BackgroundWorker();
    private readonly string _ConnectionString = "LoremIpsum";


    // ##############################################################################################################################
    // Events
    // ##############################################################################################################################

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        try
        {
            _BackgroundWorker.DoWork += _BackgroundWorker_DoWork;
            _BackgroundWorker.RunWorkerCompleted += BackgroundWorker_OnRunWorkerCompleted;
            _BackgroundWorker.RunWorkerAsync();
            prg2.Visibility = Visibility.Visible;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void _BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        e.Result = _HardWork();            
    }

    private void BackgroundWorker_OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
    {
        if(runWorkerCompletedEventArgs.Result != null)
        {
            dataGrid1.itemsSource = (DataView)runWorkerCompletedEventArgs.Result;                
        }
        else
        {
            MessageBox.Show("Failed to load data..");
        }
        prg2.Visibility = Visibility.Hidden;
    }

    // ##############################################################################################################################
    // Private Methods
    // ##############################################################################################################################

    private DataView _HardWork()
    {
        using (SqlConnection con = new SqlConnection(_ConnectionString))
        {
            con.Open();
            DataTable dataTable = new DataTable();
            SqlCommand sqlCommand = new SqlCommand("Select ...", con) {CommandTimeout = 0};
            SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
            sqlDataAdapter.Fill(dataTable);
            con.Close();
            return dataTable.DefaultView;
        }
    }