1

我正在尝试实现 MVP 模式并且我在事件处理程序方面遇到了一些问题。最初我在部分类中声明了这一点。因为它包含逻辑我假设它应该被移动到演示者中?

不过,当我将 InvokeRequired/invoke 移到 Presenter 时,它显然会产生错误。因此,除了将整个方法留在视图中之外,我想出的唯一其他选择是将事件处理程序留在视图中,因此 InvokeRequired 等不会有任何问题,而是移动 EventHandler 的主体,即动作委托,进入演示者。我不知道这样的方法调用将如何工作,尽管我使用 DI atm 在 View -> Presenter 之间进行通信,但不确定如何获取 Presenter -> View。

    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();
    }
4

1 回答 1

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,它就是。

于 2012-08-21T18:36:21.090 回答