如何使用MVP处理FormClosing

时间:2009-06-08 17:38:04

标签: c# winforms mvp

这里是:

我的观点如下:

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

然后我有一个窗体,有一个取消按钮,一个保存按钮和所有显示地址的控件。取消按钮运行:

m_addressPresenter.CancelButtonClicked();

反过来检查视图是否脏,并提示用户放弃任何更改。这很棒,这就是我想要的。

现在我的问题是如果用户在没有单击取消的情况下关闭表单(即他们单击右上角的“X”或甚至点击ALT + F4),如何实现相同的目标。我已经尝试过处理FormClosing事件,但我最终复制了一些代码,如果单击取消按钮,则会弹出两次。这就是我所拥有的:

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

3 个答案:

答案 0 :(得分:2)

我知道这已经过时了,但我起初觉得这对我来说也是一件令人困惑的事情。这是我处理这个的方式。希望有人偶然发现并发现这很有用。

在视图的界面中。

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

除了完整性之外没有任何理由,我也包括了丢弃更改检查。这样可以保持视图清晰,并将逻辑隐藏在演示者中。我希望它有所帮助。 :)

答案 1 :(得分:0)

你遇到的主要问题是视图包含演示者负责的逻辑,所以我会将演示者的CancelButtonClicked方法更改为:

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

返回值表示视图是否应该继续关闭。

取消按钮单击和表单关闭事件视图中的两个事件处理程序将查询演示者以查看它们是否应继续关闭,例如。

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

答案 2 :(得分:0)

如果有人遇到这个问题并想要一个简单的解决方案。

如果您的演示者创建了视图的实例,然后将其打开,请将其放入演示者的构造函数中:

form1.FormClosed += OnFormClose; //form1 is the name of the form that the presenter opens

以及下面的处理程序:

private void OnFormClose(object sender, EventArgs e)
        {
            Application.Exit();
        }