Reputation: 334
I am building a Windows Forms application that I would like to potentially port to WPF and GTK# in the future. I am interested in using the MVP pattern to accomplish this.
For a simple preferences dialog I have a designer created form that implements a view interface with events that the presenter can listen for when the dialog is saved or closed. I use the designer to create data bindings between the preferences frame's controls and the .NET project settings, so I am doing supervising presenter.
interface IPreferencesDialogView
{
event EventHandler Save;
event EventHandler Cancel;
}
public partial class PreferencesDialog : Form, IPreferencesDialogView
{
private PreferencesDialogPresenter presenter = null;
public event EventHandler Save;
public event EventHandler Cancel;
public PreferencesDialog()
{
InitializeComponent();
presenter = new PreferencesDialogPresenter(this);
}
private void PreferencesDialog_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.DialogResult == DialogResult.OK)
{
Save?.Invoke(this, EventArgs.Empty);
}
else
{
Cancel?.Invoke(this, EventArgs.Empty);
}
}
}
My model uses the .NET project settings to store application settings since it is available in Mono and I can use it with both WPF and GTK#.
class PreferencesDialogPresenter
{
private readonly IPreferencesDialogView view;
public PreferencesDialogPresenter(IPreferencesDialogView view)
{
this.view = view;
view.Save += (o, e) => { Properties.Settings.Default.Save(); };
view.Cancel += (o, e) => { Properties.Settings.Default.Reload(); };
}
}
On my main form I also some very specific code to Windows Forms, a cascade button which cascades all open MDI windows. It's very simple using the LayoutMdi method provided by Windows Forms (something Java Swing does not have).
private void cascade_Click(object sender, EventArgs e)
{
this.LayoutMdi(MdiLayout.Cascade);
}
This to me seems to be working great so far. The view knows nothing about the model or the presenter and the model knows nothing about the view or the presenter. However, I have a few questions.
Upvotes: 0
Views: 747
Reputation: 21
Is there anyway to simplify my event patterns? I really don't like having to pass arguments I do not use.
Ideally I would have only a single event, Closed, and I would forward the dialog result to the presenter. I do not like the Save/Cancel logic being in the view. However, the DialogResult type is Windows Forms specific, so I can't use it with GTK#. Could I create my own wrapper type? Is that what is usually done?
Yes, what I do and believe is the best practice is to create specific events that are related to the action occurring. NOT just passing events up from the UI. So, a single Close event including a simple enum to indicate whether to save or cancel. Your presenter would contain the logic to determine based on that enum whether to do Properties.Settings.Default.Save(); or Properties.Settings.Default.Reload();
Then in your non Windows Forms view, you would still need to invoke that event, but it would be up to the view to decide whether to save or cancel all the time, or whether to implement a custom Save/Cancel dialogue to get this info from the user.
Upvotes: 2