Как обрабатывать FormClosing с использованием MVP - PullRequest
1 голос
/ 08 июня 2009

Вот так:

У меня есть вид, который выглядит следующим образом:

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 ]

2 голосов
/ 20 марта 2012

Я знаю, что это старо, но я сначала почувствовал, что это сбивает с толку и меня. Это способ, которым я справился с этим. Надеюсь, кто-то спотыкается и находит это полезным.

В интерфейсе для просмотра.

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

Ни для чего, кроме полноты, я включил также проверку изменений сброса. Это обеспечивает чистоту изображения и скрытую логику в докладчике. Я надеюсь, что это помогает. :)

0 голосов
/ 25 сентября 2018

Если кто-нибудь столкнется с этим и захочет простое решение.

Если докладчик создает экземпляр представления, а затем открывает его, поместите его в конструктор докладчика:

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

И обработчик ниже:

private void OnFormClose(object sender, EventArgs e)
        {
            Application.Exit();
        }
0 голосов
/ 08 июня 2009

Основная проблема, с которой вы столкнулись, состоит в том, что представление содержит логику, за которую отвечает докладчик, поэтому я бы изменил метод 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...