2015-11-01 215 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! –

相关问题