1

MVP パターンを実装しようとしていますが、イベント ハンドラーに問題があります。もともと私はこれを部分クラスで宣言しました。ロジックが含まれているため、プレゼンターに移動する必要があると想定していますか?

ただし、InvokeRequired/invoke をプレゼンターに移動すると、明らかにエラーが発生します。したがって、メソッド全体をビューに残すこととは別に、私が思いついた他の唯一のオプションは、イベントハンドラーをビューに残すことです。そのため、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();
    }
4

1 に答える 1

2

あなたの特定のケースでは、基本的に - 少なくともコード スニペットで確認できることから - 最終的にユーザーに表示するログ メッセージ文字列を決定していますよね?

Funcでは、ではなくを使用するのはActionどうでしょうか。そうすればFunc、そこにあるロジックを使用してプレゼンター側でデリゲートを作成し、logMessage を作成して、ビューが実行したときにそれを返すことができます。

これにより、ロジックはプレゼンター側に保持され、UI に関する詳細は UI 側に保持されます。Invoke を呼び出す必要があるかどうかは、実際には UI の問題であり、プレゼンターの問題ではありませんよね? その Invoke コードを UI に貼り付けて、渡された 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();
}

したがって、プレゼンターが知る限り、Func引数を渡すことで呼び出すことができるUpdateLogメソッドを持ついくつかのIView(または、あなたが何かを行う-プレゼンターにはIViewがあると想定していましたが、何でも)があります。

ビューが知る限り、その UpdateLog メソッドは誰かによって呼び出され、Func が出力するものは何でも使用されますが、UI はそれを使用します。私の例では、いくつかのコントロールのテキストを結果に設定しただけです。Invoke を呼び出す必要がある場合は、呼び出します。

于 2012-08-21T18:36:21.090 に答える