Model view controller 如何从业务/模型类发送进度更新?
假设我们有一个具有分层体系结构的应用程序。在视图上,我们使用MVC或MVVM。该模型被视为域,它具有很好的业务逻辑部分 现在让我们假设,在模型中,有一种方法需要一些时间。一种复杂的计算或处理方法,例如,必须对一个物体的每一项进行计算或处理 在UI中,我们希望显示一个进度条和一个显示当前计算步骤的文本(例如,一个包含所有流程历史记录的列表框)Model view controller 如何从业务/模型类发送进度更新?,model-view-controller,architecture,mvvm,Model View Controller,Architecture,Mvvm,假设我们有一个具有分层体系结构的应用程序。在视图上,我们使用MVC或MVVM。该模型被视为域,它具有很好的业务逻辑部分 现在让我们假设,在模型中,有一种方法需要一些时间。一种复杂的计算或处理方法,例如,必须对一个物体的每一项进行计算或处理 在UI中,我们希望显示一个进度条和一个显示当前计算步骤的文本(例如,一个包含所有流程历史记录的列表框) 你会怎么做?如何从模型中发送流程进度信息,以及如何连接控制器或ViewModel以更新进度?您需要探索观察者模式(http://en.wikipedia.o
你会怎么做?如何从模型中发送流程进度信息,以及如何连接控制器或ViewModel以更新进度?您需要探索观察者模式(http://en.wikipedia.org/wiki/Observer_pattern). 对于桌面应用程序来说,这是非常常见的方法。对于网络来说,这有点复杂。你们可能还想看看彗星[http://en.wikipedia.org/wiki/Comet_(编程)]以查看它是如何为Web完成的。我通常以以下方式实现这一点。我的业务层流程需要很长时间才能运行,每隔一段时间就会引发一些事件,表明它正在达到特定的“里程碑”。您可以决定通过事件传达哪些里程碑以及其中的多少。如果您的耗时流程是一个普通循环,那么您可以选择,例如,每循环中的项目的10%,一次又一次地引发相同的事件。如果是一个具有不同阶段的流程,您可以选择在每个阶段完成时引发不同的事件 现在,您的表示层订阅这些事件,并相应地进行操作,更新进度条、文本或其他内容 这种机制很好,因为:
希望这能有所帮助。我对类似的案例采取了以下方法。这个观点有一个可能需要很长时间的行动,我想定期展示进展。长时间运行的操作被下推到另一个类Worker中。某些用户操作启动对TestViewModel中的
DoSomething
的调用
TestView.xaml
...
<!-- Progress bar -->
<ProgressBar Visibility="Visible" Height="10" Value="{Binding SomeValue}"/>
...
我建议查看
System.ComponentModel
命名空间中提供的BackgroundWorker
类
- (winforms示例,但前提成立)
ReportProgress
、ProgressChanged
和RunWorkerCompleted
)
实际上,我个人一直在尝试在web环境中使用BackgroundWorker
,以运行计划任务。我决定在codeplex上发表我迄今为止所做的工作。我觉得我的代码的精神对你的情况很有用
如果您选择下载项目,您将看到我如何在ScheduledTaskRunner
类中使用BackgroundWorker
类。我的实现没有将进度事件附加到worker,但是这样做非常容易。此外,我当前的实现侧重于在给定的时间间隔内运行任务,但将其修改为更像“按需”处理队列并不困难。现在我想起来,我甚至可以把它作为一个功能来添加:)
假设您遵循上面我的代码的方法,那么就很容易在您的控制器上创建一个操作,该控制器将检查“任务”(或您感兴趣的特定任务)列表,并将信息报告为某种类型的ActionResult
。设置一些javascript以在指定的时间间隔轮询操作,您将获得您的进度
祝你好运,如果你对我的代码有任何疑问,请告诉我。基于你的其他评论,你正在努力保持你的业务层尽可能干净 然后,模型视图模型方法可能适合: 计算完成后,抛出已取得进展的事件 这些事件将在ViewModel中捕获,并更新进度量
由于ViewModel和视图(观察者模式)之间的数据绑定,视图随后被更新。我当然想到了观察者模式,因为它在.Net中非常常见。但我觉得这是不对的,因为这意味着在业务中有技术方面的东西,我觉得这有点错误。谢谢你的完整回答。我认为这些事件是一个非常技术性的问题,在业务层没有它的位置。但最终必须有一种方法来发送有关流程进展情况的信息。@Gimly:不客气。我认为在业务层中,事件对于实现“活动”对象很有用;你问题中的情景就是一个很好的例子。回答得很好!那么,Form.cs文件是否应该填充您自己对象的EventHandler?
...
private void DoSomething(){
Worker worker = new Worker();
worker.ProgressChanged += new EventHandler<WorkerEventArgs>(OnProgressChanged);
worker.Start();
}
private void OnProgressChanged(object sender, WorkerEventArgs args){
SomeValue = args.Progress;
}
private const String SomeValuePropertyName = "SomeValue";
private double someValue;
public double SomeValue
{
get
{
return someValue;
}
set
{
if (someValue == value)
{
return;
}
someValue = value;
NotifyPropertyChanged(SomeValuePropertyName);
}
}
...
...
public event EventHandler<WorkerEventArgs> ProgressChanged;
public void Start(){
//This will take a long time. Periodically call NotifyProgress
}
private void NotifyProgress()
{
if (ProgressChanged != null)
{
double progress = ...; //calculate progress
ProgressChanged(this, new WorkerEventArgs(progress));
}
}
...
public class WorkerEventArgs : EventArgs
{
public double Progress { get; private set; }
public WorkerEventArgs(double progress)
{
Progress = progress;
}
}