2013-05-24 22 views
8

Şu anda SharePoint sitelerine çağrı yapmak ve Grup ve Kullanıcı bilgileri oluşturmak için SharePoint COM kullanan bir basit WPF 3.5 uygulaması yazıyor. Bu süreç bir süre sürdüğü için gruplar oluşturulurken bir ProgressBar göstermek istiyorum.WPF'de BackgroundWorker ile Kullanıcı Arabirimini Güncelleme

  1. Kullanıcı url girer ve site verilerini almak için düğmeyi tıkladığında şu şekildedir: istenen bir süreçtir.
  2. ProgressBar animasyonu
  3. Gruplar oluşturulur ve isimler tamamlama ProgressBar animasyon üzerine bir ListView
  4. eklenir başlar İçine çalıştırıyorum sorun arayüzü güncellenmemiş asla olmasıdır

biter. Ne ProgressBar veya ListView herhangi bir değişiklik yapar. Aşağıdaki kodla ilgili yardım edecek herhangi bir fikri varsa, bu çok takdir edilecektir.

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; 
     } 
     )); 
} 

cevap

7

:

var worker = (BackgroundWorker)sender; 
worker.ReportProgress(progressAmount); 

İyi burada örnek çalıştı ProgressChanged olaylarını desteklemeniz gerekiyor. Bir OnProgressChanged işleyicisi eklemek zorunda Bundan sonra

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); 

: sizin BackgroundWorker başlatmayı güncelleyin

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

Bu nedenle değiştirmek zorunda senin DoWork: çünkü sen var

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); 
    } 
} 

' GUI'yi DoWork üzerinde değiştirmeye izin verilmiyor.

Bundan sonra, her ListViewItem, ListView ürününüze ayrıca eklenir. Ayrıca, URL’nizin RunWorkerAsync'a bir argüman olarak iletilmesini de öneriyorum.

Edit: YüzdeOnProgressChanged'a ekleyin.

+0

Cevabınız için teşekkürler. Ne yazık ki, hiçbir GUI güncellemesi yok. Ayrıca, hata ayıklama sırasında, ilerleme değişti olayı asla vurulmaz. Hemen worker_RunWorkerCompleted'de kesintiye uğrar (???) – pstricker

+0

Bu döngüye hiç denemeyi/yakalamayı başardınız mı? – Kooki

+0

Ufak elemanlar (GroupListView ve SiteUrlTextBox) 'a basılan kodu, tuşa basma olayına yönlendiren küçük bir tinkeringden sonra try/catch'a ulaşabildim ancak şimdi ListViewItem'i başlatırken bir istisna atar: STA ol, çünkü birçok UI bileşeni bunu gerektirir. " – pstricker

1

Sen gerekir: in Sonra

mWorker.WorkerReportsProgress = true; 
mWorker.ProgressChanged += 
    new ProgressChangedEventHandler(worker_ProgressChanged); 

senin DoWork aramak gerekir: Size İlk başta http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

+0

Cevabınız için teşekkür ederiz. Ne yazık ki, ilerleme çubuğunu bir değerle güncellemeye çalışmıyorum, sadece Belirsiz animasyonu göstermek istiyorum. – pstricker

+0

Bu durumda, sadece ".IsIndeterminate = true;" gibi bir çağrıyı çağırmanız gerekmiyor. Aynen ".IsIndeterminate = false; – paul

2

DoWork yönteminizde, WPF denetimlerini, yapmamanız gereken bir arka plan iş parçacığındaki kodda değiştiriyorsunuz. Aslında, "Diğer iş parçacıklarından denetime erişilemiyor" gibi hatalar almalısınız. Muhtemelen bu istisnalar, yakalama hata işleyiciniz tarafından yakalanır ve belki de MessageBox bile arka plan iş parçacığı çalışmaz.

Hızlı bir düzeltme olarak, siteURL ve collGroups sınıf alanlarını oluşturmanız, GetGroupsAndUsersButton_Click yöntemine, kullanım bloğundan önce her şeyi taşıyabilmeniz ve ilk foreach döngüsünden RunworkerCompleted olayına kadar olan her şeyin yoluna girmeniz gerekir, böylece tüm kodlar erişilir denetimleri UI iş parçacığı üzerinde çalışır.

Değiştirmeniz gereken başka bir şey de, ListViewItems'i kod içinde oluşturmamanız, ancak bunun yerine bir DataTemplate kullanmanızdır ... bununla birlikte, sorununuza bağlı değilsiniz.