2012-05-14 29 views
1

我在這裏有一個例子,它複製了我試圖完成的任務。 由於下面的代碼將顯示 - 我有ViewModel更新綁定到視圖的ObservableCollection屬性。通常我會從模型中檢索的結果更新集合,但希望這個例子足夠了。在具有長時間運行的進程的視圖上使用MVVM

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Windows.Controls; 

namespace MVVMWpf.ViewModel 
{ 
    public class ListViewModel 
    { 

     public ObservableCollection<int> SomeObjectCollection { get; set; } 

     public ListViewModel() 
     { 

      SomeObjectCollection = new ObservableCollection<int>(); 

     } 

     public void Do() 
     { 
      for (int i = 1; i < 1000000; i++) 
      { 
       int i1 = i; 
       SomeObjectCollection.Add(i1); 
      } 
     } 

    } 
} 

不幸的是,這會阻止這個用戶界面。它只會更新View when循環運行完成。我解決它的方式打破了MVVM的概念。這就是爲什麼我需要你的幫助。我這樣做了。

public class ListViewModel 
{ 
    private delegate void LongRunningProcess(); 
    public ObservableCollection<int> SomeObjectCollection { get; set; } 
    private ListBox listBox; 
    public ListViewModel(ListBox listBox) 
    { 
     this.listBox = listBox; 
     SomeObjectCollection = new ObservableCollection<int>(); 

    } 

    public void Do() 
    { 
     Thread thread = new Thread(() => 
     { 
      for (int i = 1; i < int.MaxValue; i++) 
      { 
       int i1 = i; 
       listBox.Dispatcher.Invoke(
        new LongRunningProcess(() => 
        SomeObjectCollection.Add(i1); 
       }}); 

     thread.SetApartmentState(ApartmentState.STA); 
     thread.Start(); 
    } 

} 

正如你所看到的,ViewModel現在知道UI中的listBox元素。看着MVVM圖,只有View應該通過綁定來引用ViewModel。如何克服這個問題? 謝謝。

+0

如何克服什麼問題? –

回答

3

你需要讓你的循環釋放對屏幕的更新 - 某種的DoEvents的()會做:

public static void DoEvents() 
{ 
    Application.Current.Dispatcher.Invoke(
    DispatcherPriority.Background,new Action(delegate { })); 
} 

添加它並調用從循環中。


使用定時器作爲另一種選擇,你的代碼看起來應該財產以後這樣的:

private System.Timers.Timer operationsTimer = new System.Timers.Timer(); 
private int x; 

在您的構造函數:

operationsTimer.Elapsed += new System.Timers.ElapsedEventHandler 
(operationsTimer_Elapsed); 
operationsTimer.Enabled = true; 

在計時器elpased:

operationsTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    operationsTimer.Enabled = false; 
    //add item to collection code 
    x++; 
    if(x<100) 
     operationsTimer.Enabled = true; 
} 
+0

大聲笑有趣,我發現這個問題後發現這個權利。但是,當我關閉程序時,它會引發異常... –

+0

另一種選擇是使用計時器而不是線程循環。 –

+0

如果我能處理這個異常,我聽起來像是我想要的解決方案。有沒有辦法在應用程序關閉時退出所有線程。也許我應該聽window.close事件 –

0

考慮使用BackgroundWorker,一種使用報告進度和已完成事件的功能執行異步任務的簡單方法。最重要的是,你不必調用調度器上的任何東西,因爲BackgroundWorker的函數被同步到UI線程。

相關問題