假設我們有一個具有分層體系結構的應用程序。在視圖上我們使用MVC或MVVM。該模型被視爲領域,它有很好的商業邏輯。如何從業務/模型類發送進度更新?
現在讓我們說我們有,在模型中,需要一些時間的方法。例如,必須對每個對象項目進行復雜的計算或處理。
在UI中,我們想顯示進度條和將顯示計算(例如,使用所有的處理歷史列表框)的當前步驟文本。
你會怎麼做?如何從模型發送進程的進度信息以及如何連接Controller或ViewModel以便更新進程?
假設我們有一個具有分層體系結構的應用程序。在視圖上我們使用MVC或MVVM。該模型被視爲領域,它有很好的商業邏輯。如何從業務/模型類發送進度更新?
現在讓我們說我們有,在模型中,需要一些時間的方法。例如,必須對每個對象項目進行復雜的計算或處理。
在UI中,我們想顯示進度條和將顯示計算(例如,使用所有的處理歷史列表框)的當前步驟文本。
你會怎麼做?如何從模型發送進程的進度信息以及如何連接Controller或ViewModel以便更新進程?
我經常通過以下方式實現這一點。我的業務層流程需要很長時間才能運行,因此每隔一段時間就會引發一些事件,以表明它正在實現特定的「里程碑」。你決定通過事件發送什麼里程碑以及其中有多少。如果你的耗時過程是一個簡單的循環,你可以選擇例如循環中每10%的項目一次又一次地引發相同的事件。如果它是一個具有不同階段的流程,那麼隨着每個階段的完成,您可以選擇提出不同的事件。
現在,你的表現層訂閱這些事件和行爲的結果,更新進度條,文本或什麼的。
這種機制是很好的,因爲:
希望這會有所幫助。
你需要探索觀察者模式(http://en.wikipedia.org/wiki/Observer_pattern)。這是桌面應用程序非常普遍的做法。這對Web來說有點複雜。您可能還想研究Comet [http://en.wikipedia.org/wiki/Comet_(programming)],看看它是如何爲Web完成的。
視圖模型和視圖(Observer模式)之間的數據綁定我想過當然觀察者模式,因爲這是很常見的.NET。但我不覺得這是對的,因爲這意味着在這個行業有技術性的東西,我覺得有點不對。 – Gimly 2011-01-26 09:18:48
我採取了以下方法來處理類似的情況。這個觀點有一個可能需要很長時間的行動,我想定期展示進展。長時間的行動被推到另一個班級,工人。某些用戶操作會在TestViewModel中啓動對DoSomething
的調用。
TestView.xaml
...
<!-- Progress bar -->
<ProgressBar Visibility="Visible" Height="10" Value="{Binding SomeValue}"/>
...
TestViewModel。CS擴展BaseViewModel,BaseViewModel只是實現INotifyPropertyChanged
...
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);
}
}
...
Worker.cs
...
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));
}
}
...
WorkerEventArgs.cs
public class WorkerEventArgs : EventArgs
{
public double Progress { get; private set; }
public WorkerEventArgs(double progress)
{
Progress = progress;
}
}
我會建議尋找在System.ComponentModel
命名空間提供的BackgroundWorker
類。
的背景工人提供您需要在一個單獨的線程運行密集型操作的方法,以及接收狀態更新(通過ReportProgress
,ProgressChanged
和RunWorkerCompleted
)。
我其實親自嘗試在網絡環境中使用BackgroundWorker
,以運行計劃任務。我決定發佈迄今爲止在Codeplex上完成的工作。我覺得我的代碼的精神可能對你的情況有用。 'Web Scheduled Task Framework' codeplex project。
如果您選擇下載該項目,您將會看到我如何在ScheduledTaskRunner
類中使用BackgroundWorker
類。我的實現不會將進度事件附加到工作人員,但這樣做很容易。另外,我當前的實現重點關注在給定時間間隔內運行任務,但將其修改爲更多「按需」處理隊列不會很困難。我甚至可以補充說,現在我認爲它是一個功能:)
假設你遵循上面我的代碼的方法,這將是很容易創建一個操作在你的控制器被開除將檢查列表'任務'(或者您感興趣的特定任務),並將信息報告爲某種ActionResult
。設置一些JavaScript來按指定的時間間隔輪詢動作,你就會有進步!
祝你好運,讓我知道如果你有任何關於我的代碼的問題。
根據您的其他意見,您試圖儘可能保持業務層的清潔。
然後模型 - 視圖 - 視圖模型方法可能適合:http://en.wikipedia.org/wiki/Model_View_ViewModel
由於calcualtion完成後,你把事件已經取得了進展。
這些事件在ViewModel中被捕獲,並且更新了進度量。
視圖被更新,由於
感謝您的非常完整的答案。我認爲事件是一個非常技術性的問題,在業務層中沒有它的地位。但最終必須有一種方法來發送有關過程如何進行的信息。 – Gimly 2011-02-02 14:01:38