2015-11-01 112 views
0

我正在使用MVVMLight和Fody在C#/ WPF中編寫一個排序算法可視化器。在我視圖模型我有一個觀察的集合是這樣的:使用MVVMLight中的ObservableCollection中的數據更新「實時」視圖

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

現在的命令(方法),我改變集合的內容(在這種情況下,我做了冒泡排序)。像這樣:

 IMutableSortAlgorithm sorter = ServiceLocator.Current.GetInstance<IMutableSortAlgorithm>(); 
     sorter.MuatbleSort(this.NumbersCollection); 

     while (!sorter.Finished()) 
     { 
      sorter.NextStep();     
      this.RaisePropertyChanged("NumbersCollection"); // not neccesary 
      Thread.Sleep(400); 
     } 

在調用sorter.NextStep()後,集合被更改。每一步之後,我嘗試通過調用RaisePropertyChanged來更新視圖並睡眠400毫秒。

因此,我基本上希望在每次更改(步驟)後更新視圖,但視圖僅在方法完成後更新。 (爲此,我甚至不需要調用RaisePropertychanged ...)

爲了方便,我可以使用後臺工作器。但我首先想要解決這個問題,而不需要額外的工作線程。由於我在主GUI線程中,因此不需要調用Dispatcher.Invoke,對吧? (我試過了,它無法正常工作..)。

有人有線索如何刷新用戶界面後,每一步?

編輯: sorter.NextStep()does 不是插入或刪除項目的列表,但它交換值。像col [i] = col [j] ...你知道 - 排序的東西。我想在UI上實現實時的更改。

回答

1

正在更新/休眠並且從不處理屬性更改事件的UI線程中的集合。

集合需要在單獨的線程中更新。 Task.Run,​​BackgroundWorker,異步操作等

這會讓你半途而廢,導致出現錯誤「此類CollectionView不支持從與分派器線程不同的線程更改其SourceCollection。

一些谷歌上搜索發現了一個線程安全的觀察的集合: Where do I get a thread-safe CollectionView?

決定以隨機數字,而不是對它們進行排序,這對我的作品

public MTObservableCollection<int> NumbersCollection 
    { 
     get { return _item.NumbersCollection; } 
    } 

    public ICommand RandomizeCommand 
    { 
     get 
     { 
      if (_randomizeCommand == null) 
       _randomizeCommand = new RelayCommand(() => 
       {       
        Task.Run(()=> 
        { 
         for (int i = 0; i < 10; i++) 
         { 
          _dataService.Randomize();         
          Thread.Sleep(TimeSpan.FromSeconds(3)); 
         } 
        });       
       }); 

      return _randomizeCommand; 
     } 
    } 

編輯:另一種方法(這是我剛剛從學)Insert delay/wait in code c#

利用DispatcherHelper.RunAsync()等待Task.Delay在UI線程中運行而不會阻塞,並且您可以使用常規的Observable集合而不是線程安全的。

public ObservableCollection<int> NumbersCollection 
    { 
     get { return _item.NumbersCollection; } 
    } 

    public ICommand RandomizeCommand 
    { 
     get 
     { 
      if (_randomizeCommand == null) 
       _randomizeCommand = new RelayCommand(() => 
       { 
        //Task.Run(() => 
        DispatcherHelper.RunAsync(async() => 
        { 
         for (var i = 0; i < 10; i++) 
         { 
          _dataService.Randomize(); 
          //Thread.Sleep(TimeSpan.FromSeconds(3)); 
          await Task.Delay(TimeSpan.FromSeconds(3)); 
         } 
        }); 
       }); 

      return _randomizeCommand; 
     } 
    } 
+0

謝謝,這是絕對正確的...系統無法更新UI,如果UI線程睡覺... :)很好的示例btw! –