使用来自 MVVMLight 中的 ObservableCollection 的数据更新 "Realtime" 中的视图
Update View in "Realtime" with data from ObservableCollection in MVVMLight
我正在使用 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.
上 realtime 进行更改
UI 线程中的集合 updating/sleeping 并且从不处理 属性 更改的事件。
集合需要在单独的线程中更新。
Task.Run、BackgroundWorker、async Action 等
这会让你半途而废,导致错误 "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."
一些谷歌搜索发现了一个线程安全的可观察集合:
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;
}
}
编辑:另一种方法(我刚从中学到)
在 UI 线程中利用 DispatcherHelper.RunAsync() await Task.Delay 到 运行 而不会阻塞,您可以使用常规 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;
}
}
我正在使用 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.
上 realtime 进行更改UI 线程中的集合 updating/sleeping 并且从不处理 属性 更改的事件。
集合需要在单独的线程中更新。 Task.Run、BackgroundWorker、async Action 等
这会让你半途而废,导致错误 "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."
一些谷歌搜索发现了一个线程安全的可观察集合: 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;
}
}
编辑:另一种方法(我刚从中学到)
在 UI 线程中利用 DispatcherHelper.RunAsync() await Task.Delay 到 运行 而不会阻塞,您可以使用常规 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;
}
}