【C#】Delegate / Event ~ イベント・画面と処理の分離 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2010/12/12/164101
https://dk521123.hatenablog.com/entry/2010/12/25/221009
https://dk521123.hatenablog.com/entry/2010/10/22/101350

の続き。

今回は、画面(ビュー)のイベントを、別のクラス(プレゼンター)側で全て行う。

 ■ ポイント1

ビュー側

1)ビュー側で、イベント定義を定義しておく
2)イベント後にプレゼンター側に処理を委譲する

プレゼンター側

3) プレゼンターのコンストラクタでビューのイベントを追加しておく
4)イベント後の処理を記述

1)ビュー側で、イベント定義を定義しておく

public event EventHandler ShowMessageOnLabel;

2) イベント後にプレゼンター側に処理を委譲する

private void button1_Click(object sender, EventArgs e)
{
    if (ShowMessageOnLabel != null)
    {
        // プレゼンターへ(★ポイント1 【2】 ★)
        this.ShowMessageOnLabel(sender, e);
    }
}

3)プレゼンターのコンストラクタでビューのイベントを追加しておく

// ビューのイベントを追加
this.view.ShowMessageOnLabel += ShowMessageOnLabel;

4)イベント後の処理を記述

private void ShowMessageOnLabel(object sender, EventArgs e)
{
    // 委譲する処理(その時にビューを更新する処理を行う。★ポイント2★で)
}

 ■ ポイント2

ビュー側

1)プレゼンターからビューを更新できるようにPublicの受け口を用意しておく

プレゼンター側

2)ビューを更新する必要がある場合、プレゼンタの処理後に、
       ポイント2 【1】で作ったPublicの受け口を使って、ビューを更新する(任意)

1)ビュー側

プレゼンターからビューを更新できるようにPublicの受け口(下の例ではメソッド)を用意しておく

サンプル

// プレゼンター → ビュー表示
public void UpdateView()
{
    // ビューの更新処理
}

2)プレゼンテーション側

ビューを更新する必要がある場合、プレゼンタの処理後に、
ポイント2 【1】で作ったPublicの受け口を使って、ビューを更新する(任意) 

サンプル

private void ShowMessageOnLabel(object sender, EventArgs e)
{
    // プレゼンタの処理
    this.view.UpdateView(); // ビューの更新(★ポイント2 【2】 ★)
}

 ■ サンプル

 Program.cs

static class Program
{
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        //オリジナル
        //Application.Run(new Form1());
        var model = new SampleModel(); // モデル
        var view = new SampleView(model); // ビュー(モデル保持)
        SamplePresenter presenter = new SamplePresenter(model, view); // プレゼンター(ビューとモデル保持)
        Application.Run(view);
    }
}

 モデル(SampleModel.cs)

public class SampleModel
{
    public string Message { get; set; }
}

 ビュー(SampleView.cs)

public partial class SampleView : Form
{
    // 保持するモデル
    private readonly SampleModel model;

    public SampleView()
    {
        InitializeComponent();
    }
    
    // モデルを受けるためのコンストラクタ
    public SampleView(SampleModel model)
        :this()
    {
        this.model = model;
    }

    // イベント定義(★ポイント1【1】 ★)
    public event EventHandler ShowMessageOnLabel;
    
    // プレゼンター → ビュー表示(★ポイント2★)
    public void UpdateView()
    {
        this.label1.Text = this.model.Message;
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
        if (ShowMessageOnLabel != null)
        {
            // プレゼンターへ(★ポイント1【2】 ★)
            this.ShowMessageOnLabel(sender, e);
        }
    }
}

 プレゼンター(SamplePresenter.cs)

public class SamplePresenter
{
    // 保持するモデルとビュー
    private readonly SampleView view;
    private readonly SampleModel model;

    // モデルとビューを受けるためのコンストラクタ
    public SamplePresenter(SampleModel model, SampleView view)
    {
        this.model = model;
        this.view = view;

        // ビューのイベントを追加(★ポイント1【3】 ★)
        this.view.ShowMessageOnLabel += ShowMessageOnLabel;
    }

    // イベント後の処理(★ポイント1 【4】 ★)
    private void ShowMessageOnLabel(object sender, EventArgs e)
    {
        this.model.Message = "Hello, World!";
        this.view.UpdateView(); // ビューの更新(★ポイント2 【2】 ★)
    }
}

 関連記事

Delegate / Event ~ 入門編 / Delegate
https://dk521123.hatenablog.com/entry/2010/12/12/164101
Delegate / Event ~ 入門編 / Event ~
https://dk521123.hatenablog.com/entry/2010/12/25/221009