C#类如何在MVP模式中进行通信 [英] C# How do classes communicate in the MVP-Pattern

查看:69
本文介绍了C#类如何在MVP模式中进行通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我对MVP模式中未知的classen之间的沟通有疑问。



我得到的任务:



我必须使用MVP模式创建一个WindowsForms-Application,这意味着Presenter知道查看器(表单)和模型,但查看器和模型一无所知(对吗?)。



表格显示一个带有两个文本框的小公式(用于名字和姓氏,两个按钮) (用于保存名称并在富文本框中显示所有已保存的名称)和丰富的文本框。



现在用户必须填写他的名字并按下按钮用于将名称保存在列表中(通用列表,或字典,或其他什么,无关紧要)。

因此,演示者必须知道查看器上的某些更改(例如,单击了保存按钮,现在必须将字符串提供给演示者。)



我相信在这一点上你知道什么是goi在这个系统可以工作的代码中。





问题:



我不知道如何告知演示者他现在必须使用名称字符串,以便他可以将其保存在模型的列表中。因为Viewer不知道Presenter



我听说过Observer,删除或捕获具有给定参数的事件,这可以由演示者捕获。但是我不知道我应该使用哪个系统如何实现和使用oberver或代表等。



我用google搜索了3天而没有令人满意的结果。 .....



我希望你们能帮助我解决这个问题:)



问候,ToShX

解决方案

你想创建一个MVP例子的正式怎么样?你想实现通常的IView接口吗?每个对象是否应仅与演示者进行通信?



请查看:[ ^ ],[ ^ ],[ ^ ]关于WinForms中MVP的想法。



如果你真的想要正式,那么你会想修改Program.cs类来控制应用程序的启动方式。

我不知道Viewer和Presenter如何通知Presenter知道什么时候他必须从中获取字符串Viewer ... 

通常,View(呃)会在有新数据或数据更改时引发事件,通常在属性中使用INotifyPropertyChanged:Presenter传递已更改的数据或有关状态的信息 - 更改它所具有的EventHandlers ubscribe到视图中的属性的OnPropertyChanged通知(呃)。

我不想修改我的Viewer。我只想通过Presenter将数据保存到Model中,并从Model通过Presenter加载数据(用于查看表单)。

因此,View(呃)引发一个Event,传递更改数据或新数据到Presenter;然后,Presenter通过调用Model上的Method将数据发送到Model进行存储。



当调用更新显示所有名称的RichTextBox的按钮时,然后引发Presenter订阅的事件,并且Presenter从Model中请求所有名称的列表,然后调用更新RichTextBox的View(呃)上的方法。


我认为你非常接近拥有类似MVP的解决方案。让我向您展示我如何重新构建您的Presenter,并让您部分了解View如何与Presenter进行交互。



首先,让我们修改Program.cs类中的默认应用程序启动代码,以便它调用一个方法,'Presenter中的ApplicationStart将被声明为静态类:

 使用系统; 
使用 System.Windows.Forms;

命名空间 MVP_View
{
静态 class 程序
{
/// < 摘要 >
/// 应用程序的主要入口点。
/// < / summary >
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );

// 由bw修改
Presenter.DataPresenter.ApplicationStart ();
}
}
}

Presenter:

 使用系统。 Collections.Generic; 
使用 System.Windows.Forms;

命名空间 Presenter
{
// < span class =code-comment>声明为static bw
public static class DataPresenter
{
// 声明静态bw
静态 Procedures_Model.DataProcedures dataprocedures = new Procedures_Model.DataProcedures ();

// 未使用bw
// 静态DataViewer dataviewer = new DataViewer();

// 未使用bw
// public delegate void SaveEventHandler(string first,string last);
// 公共静态事件SaveEventHandler SaveHandler;

// 未使用bw
// 静态类无参数ctor
// static DataPresenter()
// < span class =code-comment> {
// // SaveHandler = new SaveEventHandler (LoadingData);
// }

// 由bw添加
public 静态 void ApplicationStart()
{
Application.Run(< span class =code-keyword> new MVP_View.DataViewer());
}

// 由bw重新命名/修改
// 注意:现在需要两个字符串参数
public static void SaveData( string 首先, string last)
{
dataprocedures.SaveData(first + + last);
}

// 未使用bw
// private static void SaveData()
// {
// dataprocedures.SaveData(dataviewer.getFullname());
// }

// 由bw添加
// 从模型中获取名称列表
public static 列表< string> GetNames()
{
return dataprocedures.load_names();
}
}
}
< / string >

现在,让我们看一下View中的一个事件如何与Presenter交互:

 < span class =code-comment> //  由bw修改 
private void but_saveNames_Click( object sender,EventArgs e)
{
// 向演示者发送名字和姓氏
Presenter.DataPresenter.SaveData(textBox_firstname.Text, textBox_surname.Text);
}

而且,这里是事件处理程序的部分草图,用于获取View中RichTextBox中显示的名称:

  //  由bw修改 
private void but_showAll_Click( object sender,EventArgs e)
{
richTextBox_allNames.Clear();

// 从DataPresenter获取名称,从模型中获取名称
// 留给你写
// 列表< string> names = ?????;

if (names.Count == 0
{
richTextBox_allNames.Text = @ 目前没有名字保存的
}
其他
{
// < span class =code-comment>留给你写

}
}

你想一想:



0.在此实现中,由于公共静态方法在Presenter中公开,导致View和Presenter存在(相对较小的)耦合...这意味着这些方法可能存在暴露给其他对象/类...什么是减少这种耦合的替代方法:使视图更愚蠢:是的,在MVP中,视图是愚蠢的好事。



1.真正的MVP架构是否需要使用接口?



2.不是真正的支付 - 使MVP架构能够创建多个视图,并在数据发生变化时启用多个视图的自动更新......这些更改可能源自任何/所有视图...界面派上用场了吗?如何在MVP实现中定义接口?



3.支持多个视图的内容以及多个视图的自动更新涉及到什么?



4.如何创建一个表单用作创建多个视图的模板,然后如何更改此模板表单的实例以删除不需要的UI元素?


到目前为止你将看到我的代码。



我想发布一个必须被演示者抓住的事件所以他知道他现在必须打电话给方法保存名字



查看:

 命名空间 MVP_View 
{
public 部分 DataViewer:表单
{
public 委托 void SaveEventHandler();
public event SaveEventHandler button_save_clicked;

public 列表< 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)
{
// 在演示者上保存全名
}

private void but_showAll_Click( object sender,EventArgs e)
{
// 在名称中加载一个列表,其中所有名称均来自演示者的模型

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





演示者:

 使用 MVP_View; 
使用 Procedures_Model;

命名空间 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());
}
}
}





型号:

< pre lang =c#> namespace Procedures_Model
{
public class DataProcedures
{
public List< string> names = new List< string>();

public 列表< string> load_names()
{
return 名称;
}

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





我不知道如何从View中触发事件以及如何捕获演示者中的这个事件!?


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

解决方案

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.


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:

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:

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:

// 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:

// 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 ?


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:

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:

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:

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!?


这篇关于C#类如何在MVP模式中进行通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆