我试图实现MVP模式,并且我遇到了一些与事件处理程序有关的问题。最初我在部分类中声明了这一点。因为它包含逻辑im假设它应该被移动到演示者?
当我将它移动到Presenter时,InvokeRequired / invoke显然会产生错误。因此,除了将整个方法留在视图中之外,我提出的唯一其他选项是将事件处理程序保留在View中,因此InvokeRequired等没有任何问题,但是移动了EventHandler的主体,即行动代表,进入演示者。我不知道这样的方法调用如何工作,因为我使用DI atm在视图之间进行通信 - >演示者,但不知道如何获得演示者 - >图。
public void CompletionReportNotifier(object sender, VerificationStatusEventArgs e)
{
Action action = () =>
{
//Display messages depending on whether it was canceled or not.
if (e.CarriedOutToCompletion == true)
{
string logMessage = string.Format("The data verification operation has been completed and {0} errors were found. Please view the error log for additional information.", inputs.NumberOfErrorsFound.ToString());
_view.UpdateLog(logMessage);
}
else
{
_view.UpdateLog("The data verification has failed. Please view the error log for additional information.");
}
//...
};
if (InvokeRequired)
Invoke(action);
else
action();
}
根据ItsMatt的回复编辑
演示者代码:
public void CompletionReportNotifier(object sender, VerificationStatusEventArgs e)
{
_view.PermanentCsvFileVerificationCancellation = null;
string logMessage;
bool inputsVisible = false;
//Display messages depending on whether it was canceled or not.
if (e.CarriedOutToCompletion == true)
{
logMessage = string.Format("The data verification operation has been completed and {0} errors were found. Please view the error log for additional information.", inputs.NumberOfErrorsFound.ToString());
}
else
{
logMessage = "The data verification has failed. Please view the error log for additional information.";
}
//Assign values to parameters depending on if it failed or errors were encountered.
if (e.CarriedOutToCompletion != true || inputs.NumberOfErrorsFound > 0)
{
inputsVisible = true;
_view.VerificationCompleted = false;
}
else
{
_view.VerificationCompleted = true;
}
_view.UIUpdate(logMessage, inputsVisible);
}
查看代码:
public void UIUpdate(string logMessage, bool inputsVisible)
{
Action action = () =>
{
UpdateLog(logMessage);
AccessToCsvFileVerificationInputs(inputsVisible);
btnDataVerification.Text = "Verify Data";
DisplayBusyMouseCursor(false);
VerifyingData = false;
};
if (InvokeRequired)
Invoke(action);
else
action();
}
答案 0 :(得分:2)
在您的具体情况下,您基本上 - 至少从我在代码片段中看到的内容 - 确定最终显示给用户的日志消息字符串,对吧?
那么使用Func
而不是Action
呢?这样你就可以在演示者一侧用你在那里获得的任何逻辑创建你的Func
委托,让它创建logMessage并在视图执行时返回它。
这样可以保持您在演示者方面的逻辑以及UI端UI的详细信息。是否需要调用Invoke实际上是一个UI问题,而不是主持人的关注,对吧?我想你只是在UI中坚持使用Invoke代码并让它执行传递给它的Func。
我在想这样的事情:
public void CompletionReportNotifier(object sender, VerificationStatusEventArgs e)
{
Func<string> func = () =>
{
string logMessage = string.empty;
//Display messages depending on whether it was canceled or not.
if (e.CarriedOutToCompletion == true)
{
logMessage =
string.Format("The data verification operation has been completed and {0} errors were found. Please view the error log for additional information.",
inputs.NumberOfErrorsFound.ToString());
}
else
{
logMessage ="The data verification has failed. Please view the error log for additional information.";
}
return logMessage;
};
_view.UpdateLog(func);
}
在视图中类似
public void UpdateLog(Func func)
{
if (InvokeRequired)
{
someControl.Invoke((MethodInvoker)(() =>
{
Invoke(whateverUi.Text = func());
}));
}
else
whateverUi.Text = func();
}
因此,只要Presenter知道,它有一些IView(或者你做的事情 - 我假设Presenter有一个IView但无论如何)有一个UpdateLog方法,可以通过传递一个Func参数来调用它
就View而言,它的UpdateLog方法被某人调用,无论Func输出被使用,UI都会使用它。在我的例子中,我只是将一些控件的文本设置为结果。如果需要调用Invoke,那就是。