WPF

2013-05-24 6 views
8

में पृष्ठभूमिवर्कर के साथ यूआई अपडेट करना मैं वर्तमान में एक साधारण WPF 3.5 एप्लिकेशन लिख रहा हूं जो SharePoint COM पर कॉल करने के लिए SharePoint COM का उपयोग करता है और समूह और उपयोगकर्ता जानकारी उत्पन्न करता है। चूंकि इस प्रक्रिया में कुछ समय लगता है, जबकि समूह उत्पन्न होने के दौरान मैं प्रोग्रेसबार दिखाना चाहता हूं। वांछित प्रक्रिया निम्नानुसार है:WPF

  1. उपयोगकर्ता साइट डेटा लाने के लिए यूआरएल और क्लिक बटन दर्ज करता है।
  2. ProgressBar शुरू होता है एनीमेशन
  3. समूह उत्पन्न कर रहे हैं और नाम एक ListView
  4. पूरा होने ProgressBar एनीमेशन पर से जुड़ जाते हैं समाप्त होता है

समस्या मैं में चल रहा हूँ कि UI को अपडेट नहीं किया जाता है। न तो प्रोग्रेसबार या लिस्ट व्यू में कोई बदलाव आता है। अगर किसी के पास नीचे दिए गए कोड में मदद करने के लिए कोई विचार है तो इसकी सराहना की जाएगी।

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

उत्तर

7

आप सबसे पहले ProgressChanged घटनाओं का समर्थन करने की आवश्यकता है। अपने BackgroundWorker प्रारंभ अद्यतन करने के लिए:

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 हैंडलर जोड़ने के लिए है:

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 पर जीयूआई बदलने की अनुमति नहीं है।

उसके बाद, प्रत्येक ListViewItem को आपके ListView पर अलग से जोड़ा गया है। मैं यह भी सिफारिश करता हूं कि आपका यूआरएल RunWorkerAsync पर तर्क के रूप में पारित हो गया है।

संपादित करें: OnProgressChanged पर प्रतिशत जोड़ें।

+0

पर कॉल करते हैं, आपके उत्तर के लिए धन्यवाद। अफसोस की बात है, अभी भी कोई जीयूआई अपडेट नहीं है। साथ ही, डिबगिंग करते समय, प्रगति में बदलाव आया घटना कभी हिट नहीं हुई। यह तुरंत कार्यकर्ता_रुनवर्कर पर टूट जाता है हालांकि (???) – pstricker

+0

क्या आपने कभी भी लूप को कोशिश/पकड़ने में पहुंचाया? – Kooki

+0

थोड़ा tinkering के बाद मैं कोड क्लिक करके कोशिश/पकड़ पकड़ने में सक्षम था जो यूआई तत्वों (GroupListView और SiteUrlTextBox) को बटन क्लिक इवेंट में संदर्भित करता है, हालांकि अब ListViewItem शुरू करते समय यह अपवाद फेंक रहा है: "कॉलिंग थ्रेड आवश्यक है एसटीए बनें, क्योंकि कई यूआई घटकों को इसकी आवश्यकता होती है। " – pstricker

1

आप की आवश्यकता होगी:

mWorker.WorkerReportsProgress = true; 
mWorker.ProgressChanged += 
    new ProgressChangedEventHandler(worker_ProgressChanged); 
तब में

अपने DoWork आप कॉल करने के लिए की आवश्यकता होगी:

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

अच्छा यहाँ उदाहरण काम किया: http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

+0

आपके उत्तर के लिए धन्यवाद। दुर्भाग्य से मैं एक मूल्य के साथ प्रगति पट्टी को अद्यतन करने की कोशिश नहीं कर रहा हूं, मैं बस अनिश्चित एनीमेशन दिखाना चाहता हूं। – pstricker

+0

यदि वह मामला है, तो आपको कॉल को 'IsIndeterminate = true' पर कॉल करने की आवश्यकता नहीं है, जैसा कि आप 'IsIndeterminate = false;' – paul

2

अपनी DoWork विधि में, आप पृष्ठभूमि थ्रेड पर कोड में WPF नियंत्रणों को जोड़ रहे हैं, जिसे आप नहीं करना चाहते हैं। दरअसल, आपको त्रुटियों को प्राप्त करना चाहिए जैसे "अन्य धागे से नियंत्रण तक नहीं पहुंच सकता"। शायद उन अपवादों को आपके पकड़-सभी त्रुटि हैंडलर द्वारा पकड़ा जाता है, और यहां तक ​​कि संदेशबॉक्स पृष्ठभूमि थ्रेड से भी काम नहीं करता है।

त्वरित सुधार के रूप में, आप siteURL और collGroups वर्ग क्षेत्रों बनाने के लिए, RunworkerCompleted घटना के लिए पहले foreach पाश के साथ शुरू अपने GetGroupsAndUsersButton_Click विधि करने के लिए ब्लॉक का उपयोग करने से पहले सब कुछ, और सब कुछ ले जाते हैं, ताकि सभी कोड है जो तक पहुँचता होता नियंत्रण यूआई थ्रेड पर चलता है।

एक और चीज जो आपको बदलनी चाहिए वह यह है कि आपको कोड में ListViewItems नहीं बनाना चाहिए, बल्कि इसके बजाय डेटा टेम्पलेट का उपयोग करना चाहिए ... हालांकि यह आपकी समस्या से जुड़ा नहीं है।

 संबंधित मुद्दे