在 WPF 中使用 BackgroundWorker 更新 UI [英] Updating UI with BackgroundWorker in WPF

查看:42
本文介绍了在 WPF 中使用 BackgroundWorker 更新 UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在编写一个简单的 WPF 3.5 应用程序,它利用 SharePoint COM 调用 SharePoint 网站并生成组和用户信息.由于此过程需要一段时间,我想在生成组时显示 ProgressBar.所需的过程如下:

I am currently writing a simple WPF 3.5 application that utilizes the SharePoint COM to make calls to SharePoint sites and generate Group and User information. Since this process takes awhile I want to show a ProgressBar while the groups are being generated. The desired process is as follows:

  1. 用户输入网址并点击按钮以获取网站数据.
  2. ProgressBar 开始动画
  3. 生成组并将名称添加到 ListView
  4. 完成后 ProgressBar 动画结束

我遇到的问题是 UI 永远不会更新.ProgressBar 或 ListView 都不做任何更改.如果有人对下面的代码有任何帮助,我们将不胜感激.

The problem I am running into is that the UI is never updated. Neither the ProgressBar or the ListView makes any changes. If anyone has any ideas to help with the code below it would be greatly appreciated.

private void GetGroupsAndUsersButton_Click(object sender, RoutedEventArgs e)
{
    siteUrl = "";

    if (SiteURLTextBox.Text.Length > 0)
    {
        FetchDataProgressBar.IsIndeterminate = true;

        mWorker = new BackgroundWorker();
        mWorker.DoWork += new DoWorkEventHandler(worker_DoWork);
        mWorker.WorkerSupportsCancellation = true;
        mWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        mWorker.RunWorkerAsync();
    }
    else
    {
        System.Windows.MessageBox.Show("Please enter a URL for the SharePoint site you wish to retrieve data");
    }
}

private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    siteUrl = SiteURLTextBox.Text;
    GroupListView.ItemsSource = null;

    try
    {
        using (SPSite site = new SPSite(siteUrl))
        {
            SPWeb web = site.OpenWeb();
            SPGroupCollection collGroups = web.SiteGroups;
            if (GroupNames == null)
                GroupNames = new List<string>();

            foreach (SPGroup oGroup in collGroups)
            {
                GroupListView.Items.Add(new ListViewItem() { Content = oGroup.Name });
            }

            foreach (ListViewItem item in GroupListView.Items)
            {
                item.MouseLeftButtonUp += item_MouseLeftButtonUp;
            }
        }
    }
    catch (Exception ex)
    {
        System.Windows.MessageBox.Show("Unable to locate a SharePoint site at: " + siteUrl);
    }
}

private void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    FetchDataProgressBar.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
    new Action(
        delegate()
        {
            FetchDataProgressBar.IsIndeterminate = false;
        }
        ));
}

推荐答案

首先你需要支持 ProgressChanged 事件.将您的 BackgroundWorker 初始化更新为:

At first you need to support ProgressChanged events. Update your BackgroundWorker initialization to:

GroupListView.ItemSource = null;
mWorker = new BackgroundWorker();
mWorker.DoWork += new DoWorkEventHandler(worker_DoWork);
mWorker.WorkerSupportsCancellation = true;
mWorker.WorkerReportsProgress = true;
mWorker.ProgressChanged += OnProgressChanged;
mWorker.RunWorkerCompleted +=
        new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
mWorker.RunWorkerAsync(SiteURLTextBox.Text);

之后你必须添加一个 OnProgressChanged 处理程序:

After that you have to add a OnProgressChanged handler:

private void OnProgressChanged(object sender, ProgressChangedEventArgs e)
{
    FetchDataProgressBar.Value = e.ProgressPercentage;
    ListViewItem toAdd = (ListViewItem)e.UserState;
    toAdd.MouseLeftButtonUp += item_MouseLeftButtonUp;
    GroupListView.Items.Add(toAdd);
}

因此你必须改变你的DoWork:

private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker)sender;            
    try
    {
        using (SPSite site = new SPSite((String)e.Argument))
        {
            SPWeb web = site.OpenWeb();
            SPGroupCollection collGroups = web.SiteGroups;
            if(GroupNames == null)
                GroupNames = new List<string>();
            int added = 0;
            foreach(SPGroup oGroup in collGroups)
            {
                added++;
                ListViewItem tmp = new ListViewItem() {
                    Content = oGroup.Name
                };
                worker.ReportProgress((added * 100)/collGroups.Count,tmp);
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unable to locate a SharePoint site at: " + siteUrl);
    }
}

那是因为您不允许在 DoWork 上更改 GUI.

That's because you're not allowed to change GUI on DoWork.

之后,每个 ListViewItem 都会单独添加到您的 ListView 中.我还建议将您的 URL 作为参数传递给 RunWorkerAsync.

After that, each ListViewItem is added separately to your ListView. I would also recommend, that your URL is passed as an argument to RunWorkerAsync.

编辑:将百分比添加到 OnProgressChanged.

这篇关于在 WPF 中使用 BackgroundWorker 更新 UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆