0

我正在使用 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 并休眠 400 毫秒来更新视图。

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

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

有人知道如何在每一步之后刷新 UI 吗?

编辑: sorter.NextStep() 不会列表中插入或删除项目,但会交换值。就像 col[i] = col[j] ...你知道 - 排序的东西。我想在 UI 上实时获得这些变化。

4

1 回答 1

1

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

集合需要在单独的线程中更新。Task.Run、BackgroundWorker、异步操作等。

这会让你半途而废,导致错误“这种类型的 CollectionView 不支持从与 Dispatcher 线程不同的线程对其 SourceCollection 的更改。”

一些谷歌搜索发现了一个线程安全的可观察集合: 我在哪里可以获得线程安全的 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;
        }
    }

编辑:另一种方法(我刚刚从中学到)在代码 c# 中插入延迟/等待

利用 DispatcherHelper.RunAsync() await 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;
        }
    }
于 2015-11-01T16:34:55.197 回答