在具有长时间运行进程的视图上使用 MVVM
本文关键字:视图 MVVM 进程 长时间 运行 | 更新日期: 2023-09-27 18:34:05
我这里有一个例子来复制我想要完成的事情。如以下代码所示 - 我有更新绑定到视图的可观察集合属性的视图模型。通常我会从从模型中检索到的结果更新集合,但希望此示例就足够了。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Controls;
namespace MVVMWpf.ViewModel
{
public class ListViewModel
{
public ObservableCollection<int> SomeObjectCollection { get; set; }
public ListViewModel()
{
SomeObjectCollection = new ObservableCollection<int>();
}
public void Do()
{
for (int i = 1; i < 1000000; i++)
{
int i1 = i;
SomeObjectCollection.Add(i1);
}
}
}
}
不幸的是,这会阻止此 UI。它只会在循环运行时更新视图。我解决它的方式打破了 MVVM 的概念。这就是为什么我需要你的帮助。我这样做了。
public class ListViewModel
{
private delegate void LongRunningProcess();
public ObservableCollection<int> SomeObjectCollection { get; set; }
private ListBox listBox;
public ListViewModel(ListBox listBox)
{
this.listBox = listBox;
SomeObjectCollection = new ObservableCollection<int>();
}
public void Do()
{
Thread thread = new Thread(() =>
{
for (int i = 1; i < int.MaxValue; i++)
{
int i1 = i;
listBox.Dispatcher.Invoke(
new LongRunningProcess(() =>
SomeObjectCollection.Add(i1);
}});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
}
如您所见,ViewModel 现在知道 UI 中的 listBox 元素。查看 MVVM 图,只有视图应该通过绑定引用视图模型。如何克服这个问题?谢谢。
你需要让你的循环释放对屏幕的更新 - 某种DoEvents()可以:
public static void DoEvents()
{
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background,new Action(delegate { }));
}
添加它并从循环中调用它。
使用计时器作为另一个选项,您的代码应如下所示:
private System.Timers.Timer operationsTimer = new System.Timers.Timer();
private int x;
在您的CTOR中:
operationsTimer.Elapsed += new System.Timers.ElapsedEventHandler
(operationsTimer_Elapsed);
operationsTimer.Enabled = true;
在你的计时器中,埃尔帕塞德:
operationsTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
operationsTimer.Enabled = false;
//add item to collection code
x++;
if(x<100)
operationsTimer.Enabled = true;
}
考虑使用 BackgroundWorker,这是一种执行异步任务的简单方法,具有报告进度和已完成事件的功能。最重要的是,您不必在调度程序上调用任何内容,因为后台工作线程的函数已同步到 UI 线程。