使用来自MVVMLight中的ObservableCollection的数据更新“实时”中的视图

时间:2015-11-01 14:15:10

标签: c# wpf mvvm-light observablecollection fody-propertychanged

我正在使用MVVMLight和Fody在C#/ WPF中编写排序算法可视化工具。在我的 ViewModel 中,我有一个可观察的集合,如下所示:

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更新View并休眠400ms。

所以我基本上希望在每次更改(步骤)后更新视图,但View仅在方法完成后更新。 (为此我甚至不需要调用RaisePropertychanged ......)

为方便起见,我可以使用后台工作人员。但我首先想要在没有额外工作线程的情况下解决问题。因为我在主GUI线程中,所以不需要调用Dispatcher.Invoke,对吧? (我尝试了,但无论如何都没有用。)。

有人知道如何在每一步之后刷新用户界面吗?

编辑: sorter.NextStep()插入或删除列表中的项目,但它交换值。就像col [i] = col [j] ......你知道 - 整理东西。我希望在UI上的实时中获得更改。

1 个答案:

答案 0 :(得分:1)

UI线程中正在更新/休眠的集合,从不处理属性更改事件。

需要在单独的线程中更新集合。 Task.Run,​​BackgroundWorker,async Action等。

这会让你走到一半,导致错误“这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其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;
        }
    }