Click here to Skip to main content
15,886,806 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi,

I have a question about the communication between unkown classen in the MVP-Pattern.

The task I got:

I have to create a WindowsForms-Application with the MVP-Pattern, which means that the Presenter knows the Viewer (the Form) and the model, but the Viewer and the Model know nothing (right?).

The Form shows a small formular with two textboxes (for firstname and lastname, two buttons (for saving the name and for showing all saved names in a rich textbox) and a rich textbox.

Now the user have to fill in his name and press the button for saving the name in a list (generic list, or dictionary, or whatever, that doesn't matters).
Therefore the Presenter must know WHEN something changes on the Viewer (e.g. saving button was clicked and now the strings must be given to the presenter).

I'm sure at this point you know what's have to going on in the code that this system will work.


The problem:

I don't know how to inform the presenter that he must now take the name-strings so that he can save it in the list in the model. Because the Viewer doesn't know the Presenter

I've heard something about Observer and delegets or catching events with given parameters, which can catched by the presenter. But I don't know which system I should use neither how to implement and use the oberver or delegates etc.

I googled for just 3 days without a satisfying result......

I hope you guys can help me to solve that problem :)

Greetings, ToShX
Posted
Updated 2-Nov-14 23:25pm
v2
Comments
ToShX 3-Nov-14 5:13am    
Yeh, I misspelled it in the title. I mean MVP-Pattern not MPV-Pattern! :P
DamithSL 3-Nov-14 5:19am    
you can edit and correct it.
BillWoodruff 3-Nov-14 8:52am    
I've added some content to my response based on your remarks in the (now deleted) comment. Let me know if you want to take this further; I have some code I wrote a few years ago I am willing to share. It does seem to me there is no one MVP implementation in WinForms that everyone agrees is the "best" :)

How "formal" an MVP example do you want to create ? Do you want to implement the usual IView interface ? Should every "object" communicate only with the "Presenter" ?

Take a look at : [^], [^], [^] for ideas on MVP in WinForms.

If you really want "formal," then you will want to modify the Program.cs class to control the way the app starts.
I don't know how the Viewer and the Presenter can communicate that the Presenter knows WHEN he has to take the strings from the Viewer...
In general, the View(er) raises events when there is new data, or data changes, often using INotifyPropertyChanged in Properties: the Presenter is passed the changed data, or information about state-change in the EventHandlers it has which subscribe to the OnPropertyChanged notifications of the the Properties in the View(er).
I don't want to modify my Viewer. I just want to save data to the Model through the Presenter and load data (for viewing in the form) from the Model through the Presenter.
So, the View(er) raises an Event, passing the changed data, or new data, to the Presenter; then, the Presenter sends the data to the Model for storage by calling a Method on the Model.

When the button that updates the RichTextBox that displays all names is called, then an Event is raised that the Presenter subscribes to, and the Presenter requests the list of all names from the Model, and then calls a method on the View(er) that updates the RichTextBox.
 
Share this answer
 
v2
I think your very close to having a working MVP-like solution. Let me show you how I'd re-structure your Presenter, and give you a partial idea of how the View can interact with the Presenter.

First, let's modify the default Application start-up code in the Program.cs Class so that it invokes a method, 'ApplicationStart in the Presenter which will be declared as a static Class:
C#
using System;
using System.Windows.Forms;

namespace MVP_View
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // modified by bw
            Presenter.DataPresenter.ApplicationStart();
        }
    }
}
The Presenter:
C#
using System.Collections.Generic;
using System.Windows.Forms;

namespace Presenter
{
    // declared static bw
    public static class DataPresenter
    {
        // declared static bw
        static Procedures_Model.DataProcedures dataprocedures = new Procedures_Model.DataProcedures();
        
        // not used bw
        //static DataViewer dataviewer = new DataViewer();

        // not used bw
        //public delegate void SaveEventHandler(string first, string last);
        //public static event SaveEventHandler SaveHandler;

        // not used bw
        // static class parameterless ctor
        //static DataPresenter()
        //{
        //    //SaveHandler = new SaveEventHandler(LoadingData);
        //}

        // added by bw
        public static void ApplicationStart()
        {
            Application.Run(new MVP_View.DataViewer());
        }

        // re-named/modified by bw
        // note: now takes two string arguments
        public static void SaveData(string first, string last)
        {
            dataprocedures.SaveData(first + " " + last);
        }

        // not used bw
        //private static void SaveData()
        //{
        //    dataprocedures.SaveData(dataviewer.getFullname());
        //}

        // added by bw
        // get the list of names from the model
        public static List<string> GetNames()
        {
            return dataprocedures.load_names();
        }
    }
}
</string>
Now, let's look at how one event in the View can interact with the Presenter:
C#
// modified by bw
private void but_saveNames_Click(object sender, EventArgs e)
{
    // send first, and last names to the presenter
    Presenter.DataPresenter.SaveData(textBox_firstname.Text, textBox_surname.Text);
}
And, here's a partial "sketch" of the event handler to get the names shown in the RichTextBox in the View:
C#
// modified by bw
private void but_showAll_Click(object sender, EventArgs e)
{
    richTextBox_allNames.Clear();

    // get names from DataPresenter which gets them from the Model
    // left for you to write
    // List<string> names = ?????;

    if (names.Count == 0)
    {
        richTextBox_allNames.Text = @"No names are currently saved.";
    }
    else
    {
        // left for you to write
    }
}
For you to think about:

0. in this implementation there is a (relatively small) "coupling" of the View and the Presenter caused by the fact that public static methods are exposed in the Presenter ... that means those methods are potentially exposed to other objects/classes ... what would be an alternative to reduce this coupling: to make the View more "stupid:" yes, in MVP, it's a good thing for the View to be stupid.

1. doesn't a real MVP architecture require use of an Interface ?

2. isn't a real pay-off of having an MVP architecture the ability to create multiple Views, and enable automatic updating of multiple Views as the data changes ... the change perhaps originating from any/all Views ... for which using an Interface comes in handy ? Where would an Interface be defined in an MVP implementation ?

3. what would supporting multiple views, and automatic updates of multiple views, involve ?

4. how would you create a Form to be used as a template for creating multiple views, and how would you then alter instances of this template Form to remove UI elements you didn't want ?
 
Share this answer
 
v2
Comments
ToShX 4-Nov-14 2:04am    
I thank you a lot for your help! I try to understand what you've done to my code and I will think about your questions!

Two months ago I just started my education as a software developer ( I started programming one year ago) and now I have a lot to learn ;)
Below you will se my code so far.

I want to fire an event which have to get catched by the presenter so that he know that he now must call the method to save the name

The View:
C#
namespace MVP_View
{
    public partial class DataViewer : Form
    {
        public delegate void SaveEventHandler ();
        public event SaveEventHandler button_save_clicked;

        public List<string> names = new List<string>();

        public DataViewer()
        {
            InitializeComponent();
        }

        public string getFullname()
        {
            string fullname = textBox_firstname.Text + " " + textBox_surname.Text;
            return fullname;
        }
        
        private void but_saveNames_Click(object sender, EventArgs e)
        {
            // Save full name over the presenter
        }
       
        private void but_showAll_Click(object sender, EventArgs e)
        {
            // Load a List in 'names' with all names from the Model over the presenter 

            foreach (var name in names)
            {
                richTextBox_allNames.Text = richTextBox_allNames.Text + "\n" + name;
            } 
        }
    }
}
</string></string>


The Presenter:
C#
using MVP_View;
using Procedures_Model;

namespace Presenter
{

    public class DataPresenter
    {
        private DataProcedures dataprocedures = new DataProcedures();
        private DataViewer dataviewer = new DataViewer();

        private delegate void SaveEventHandler();
        private event SaveEventHandler SaveHandler;

        public DataPresenter()
        {
            this.SaveHandler += new SaveEventHandler(LoadingData);
        }
        
        private void LoadingData()
        {
           
        }

        private void SaveData()
        {
			dataprocedures.SaveData(dataviewer.getFullname());
        }
    }
}


The Model:
C#
namespace Procedures_Model
{
    public class DataProcedures
    {
        public List<string> names = new List<string>();

        public List<string> load_names()
        {
            return names;
        }

        public void SaveData(string fullName)
        {
            names.Add(fullName);
        }
    }
}</string></string></string>


And I don't know how to fire the event from the View and how to catch this event in the Presenter!?
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900