2

ここに行きます:

次のようなビューがあります。

public interface IAddressView
{
     void Close();
     bool IsDirty();
     bool DoesUserWantToDiscardChanges();
}

次のようなプレゼンターがあります。

public class AddressViewPresenter
{
    private IAddressView m_addressView;
    private Address m_address;

    public AddressViewPresenter(IAddressView addressView)
    {
        m_addressView = addressView;
        m_address = new Address();
    }

    public void CancelButtonClicked()
    {
        bool canClose = true;

        if (m_addressView.IsDirty())
        {
            canClose = m_addressView.DoesUserWantToDiscardChanges();
        }

        if (canClose)
        {
            m_addressView.Close();
        }
    }

    public void SaveButtonClicked()
    {
        // saving logic goes here...removed for brevity
        m_addressView.Close();
    }
}

次に、キャンセル ボタン、保存ボタン、およびアドレスを表示するためのすべてのコントロールを備えた Windows フォームを作成します。キャンセル ボタンが実行されます。

m_addressPresenter.CancelButtonClicked();

次に、ビューがダーティかどうかをチェックし、変更を破棄するようにユーザーに促します。これは素晴らしいです、それは私が欲しいものです。

ここで私の質問は、ユーザーが [キャンセル] をクリックせずにフォームを閉じた場合 (つまり、右上の [X] をクリックしたり、ALT + F4 を押したりした場合) に同じことを達成する方法です。FormClosing イベントを処理しようとしましたが、一部のコードを複製してしまい、キャンセル ボタンをクリックするとポップアップが 2 回発生します。ここに私が持っているものがあります:

private void AddressForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (this.IsDirty())
    {
        if (!this.DoesUserWantToDiscardChanges())
        {
            e.Cancel = true;
        }
    }
}
4

3 に答える 3

3

これが古いことは知っていますが、最初はこれも混乱を招くものだと感じました。これが私がこれを処理した方法です。うまくいけば、誰かがつまずいて、これが役に立つと思います.

ビューのインターフェイス。

public interface IMainScreenView
{
    event BoolHandler CloseView;

    bool IsDirty { get; set; }
    bool WillDiscardChanges();
}

次に、プレゼンターで close 関数を CloseView イベントにサブスクライブします。

public MainScreenPresenter(IView _view)
{
    _view.CloseView += Close;
}

private bool Close()
{
    bool close = true;

    if (_view.IsDirty)
        close = _view.WillDiscardChanges();

    return close;
}     

これで、ビュー自体で、通常どおり FormClosing イベントをサブスクライブし、CloseView イベントを利用できるようになりました。

public MainForm()
{
    InitializeComponent();

    _presenter = new MainScreenPresenter(this);
    FormClosing += UxMainScreenFormClosing;
}

public bool WillDiscardChanges()
{
    return MessageBox.Show("Changes have been made without being saved. Would you like to continue?", "Exiting", MessageBoxButtons.YesNo) == DialogResult.Yes;
}

protected void UxMainScreenFormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = !CloseView();
}

完全を期すという理由だけで、変更の破棄チェックも含めました。これにより、ビューがきれいに保たれ、ロジックがプレゼンターに隠されます。お役に立てば幸いです。:)

于 2012-03-20T16:21:58.250 に答える
0

あなたが抱えている主な問題は、プレゼンターが担当するロジックがビューに含まれていることです。そのため、プレゼンターの CancelButtonClicked メソッドを次のように変更します。

public bool ViewRequestingClose()
{
    bool canClose = true;
    if (m_addressView.IsDirty())
    {
        canClose = m_addressView.DoesUserWantToDiscardChanges();
    }
    return canClose;
}

戻り値は、ビューを閉じ続ける必要があるかどうかを示します。

キャンセル ボタンのクリックとフォームを閉じるイベントのビュー内の 2 つのイベント ハンドラーは、プレゼンターにクエリを実行して、閉じ続ける必要があるかどうかを確認します。

private void AddressForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if(!m_addressPresenter.ViewRequestingClose())
        e.Cancel = true;
}

private void CancelButton_Click(object sender, FormClosingEventArgs e)
{
    if(m_addressPresenter.ViewRequestingClose())
        this.Close();
}
于 2009-06-08T18:12:45.507 に答える