Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用MVP处理表单关闭_C#_Winforms_Mvp - Fatal编程技术网

C# 如何使用MVP处理表单关闭

C# 如何使用MVP处理表单关闭,c#,winforms,mvp,C#,Winforms,Mvp,下面是: 我有这样一个观点: public interface IAddressView { void Close(); bool IsDirty(); bool DoesUserWantToDiscardChanges(); } public class AddressViewPresenter { private IAddressView m_addressView; private Address m_address; public

下面是:

我有这样一个观点:

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();
    }
}
public bool ViewRequestingClose()
{
    bool canClose = true;
    if (m_addressView.IsDirty())
    {
        canClose = m_addressView.DoesUserWantToDiscardChanges();
    }
    return canClose;
}
我的演示者如下所示:

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();
    }
}
public bool ViewRequestingClose()
{
    bool canClose = true;
    if (m_addressView.IsDirty())
    {
        canClose = m_addressView.DoesUserWantToDiscardChanges();
    }
    return canClose;
}
然后我有一个windows窗体,它有一个取消按钮、一个保存按钮和所有显示地址的控件。“取消”按钮运行:

m_addressPresenter.CancelButtonClicked();
然后检查视图是否脏,并提示用户放弃任何更改。这太好了,这正是我想要的

现在我的问题是,如果用户关闭表单而不单击取消(即,他们单击右上角的“X”,甚至单击ALT+F4),如何实现同样的效果。我曾尝试处理FormClosing事件,但最终复制了一些代码,如果单击“取消”按钮,弹出窗口会出现两次。以下是我所拥有的:

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

您遇到的主要问题是视图包含演示者负责的逻辑,因此我将演示者上的CancelButtonClicked方法更改为类似以下内容:

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

我知道这已经很老了,但一开始我觉得这对我来说也是一件令人困惑的事情。我就是这样处理的。希望有人会发现这很有用

在视图的界面中

public interface IMainScreenView
{
    event BoolHandler CloseView;

    bool IsDirty { get; set; }
    bool WillDiscardChanges();
}
然后在演示者中,将关闭功能订阅到CloseView事件

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

private bool Close()
{
    bool close = true;

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

    return close;
}     
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();
}
现在,在视图本身中,您可以像往常一样订阅FormClosing事件并使用CloseView事件

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

private bool Close()
{
    bool close = true;

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

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

除了完整性之外,没有其他原因,我也包括了放弃更改检查。这样可以使视图保持干净,并将逻辑隐藏在演示者中。我希望这能有所帮助

如果有人遇到这种情况,想要一个简单的解决方案

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

form1.FormClosed += OnFormClose; //form1 is the name of the form that the presenter opens
和下面的处理程序:

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

这样做更有意义。但是,我仍然遇到这样的问题:当您单击“取消”按钮时,它会两次询问您是否要放弃更改。您会收到双重提示,因为当确认取消时,它将关闭表单,其逻辑与仅尝试关闭表单时的逻辑相同。您可以使用bool来跟踪关闭是从Alt+F4/“x”单击还是取消单击开始的,并且只在第一次通过时提示。是的。我只是希望能有不同的做法。它的工作原理与您描述的一样,如果我添加bool来跟踪关闭是否来自取消按钮。我想这样使用bool感觉有点“笨拙”。我想如果成功了,它也会成功。谢谢。为什么不干脆
this.Close()
取消按钮中单击
?它的效果与使用布尔值表示关闭来自
CancelButton\u单击