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单击