简体   繁体   中英

ASP.NET MVP Pattern

I'm trying to implement the Model-View-Presenter design pattern in my application. The general concept of the MVP pattern is known for me, but I'm more struggling with getting it done using nested usercontrols.

I've got a few possible scenarios I might be able to implement, but before doing so I'd like to hear your opinion.

I think it does not matter to post any of my code, since its more a "concept" I'm trying to understand.

So the scenario is:

1 page used to connect 2 user controls. One of these usercontrols contains a child usercontrol. How do I work around with MVP pattern in this case?

1 Page
  1 UC
  1 UC
     1 SubUC

Edit:

So basicly what I want to know is how we can interact between two views (parent and child) using MVP in both usercontrols.

I'll show you an example in ASP.net WITHOUT MVP: http://pastie.org/5452134

Now with MVP, do we still register to this kind of event using the CodeBehind? Knowing that this parent and child usercontrol would both be using the MVP pattern. Or does the presenter get's included in this interaction?

Eventually I can change the code to: http://pastie.org/5452180

But I'm wondering whether this is OK, considering the MVP pattern...

Or do we more need an approach like this: http://pastie.org/5452174

All the above examples are written in the CodeBehind of the parent view. Is one of this correct? If not, how can we achieve this using a better approach

Edit 2: I've added a solution with my example approach at: https://github.com/frederikprijck/ASP.NET-MVP I think this should be pretty much what I wanted...

I don't see a problem - user control is nothing but a view. And a presenter can interact with multiple views at a time. So in this case, your presenter can have reference of say 4 views (one for page, two for user controls and last one for sub-user control).

Alternatively, you want to have single view per presenter and in such case, you can see user control as child view of the parent view(page) and so parent view need to bubble up and down view interactions meant for presenter. However, I would prefer the earlier approach where presenter handling interaction multiple views.

See this related question on SO on how wiring is done: https://softwareengineering.stackexchange.com/questions/60774/model-view-presenter-implementation-thoughts

Finally, you may want to look at MVVM pattern which I believe works great for compositional UI. Instead of presenter, you will have view model that will control the interaction between view and model - however, unlike presenter, view model does not know about view - rather view observes (and updates) view model to render itself. See this article here (View Model is referred as Presentation Model): http://www.codeproject.com/Articles/23340/Presentation-Model-in-Action

EDIT :

To be honest, I don't prefer any of your approaches. I like MVP implementation where presenter holds reference to view via interface (no tight coupling) and view does the wiring ie creates presenter instance and inject the view references. The presenter listens to view events and call methods on view. View never calls directly on presenter's methods. (Other variations of MVP are possible - see the SO answer that I had sought). With this, I will explain two approaches that I had explained earlier.

Approach 1 :

Each user control is an independent view. There will be common presenter that will handle multiple views. For example,

public class Presenter1
{
    IView1 _view1;
    IView2 _view2;

    public Presenter1(IView1 view1, IView2 view2)
    {
        _view1 = view1;
        _view2 = view2;

        _view1.OnSave += OnSave;
        _view1.OnSomeEvent += OnSomeEvent;
        _view2.OnFoo += OnFoo;
    }

    public void OnSave()
    {
        var data1 = _view1.GetData();
        var data2 = _view2.GetData();
        // update model
        ...
    }

    public void OnSomeEvent()
    {
       // inform view2 about it
       _view2.DoOnSomeEvent();
    }

    ...
}

public partial class MyPage : Page, IView1
{
   public void Page_Load(...)
   {
     //do wire up
     _presenter = new Presenter(this, usercontrol1);
   }
   ...
}

Basic idea is that view does not do cross talk. If user control needs to inform page some thing, it would raise an event that is caught by presenter and it informs page about it. Views are passive and handles UI.

Approach 2:

Usercontrol and Page interacts. In such case, Page will act as a ultimate view and Presenter will hold reference to it. Control's events will be handled by page and page will bubble up the event if necessary. For example,

IView1 : IView2 { }

public class Presenter1
{
   IView1 _view1;

   public Presenter1(IView1 view1)
   {
       _view1 = view1;

       _view1.OnSave += OnSave;
       _view1.OnSomeEvent += OnSomeEvent;
       _view1.OnFoo += OnFoo;
   }
   ...
}

public partial class MyPage : Page, IView1
{
       public void Page_Load(...)
       {
         //do wire up
         _presenter = new Presenter(this);

         // handle user control events
         UserControl1.Foo += UserControl1_OnFoo();
         UserControl1.XyzEvent += UserControl1_XyzEvent();

       }
       ...

       private void UserControl1_OnFoo(...)
       {
          // bubble up to presenter
          OnFoo(..)
       }

       private void UserControl1_XyzEvent(...)
       {
          // private interaction (purely about some UI manipulation), 
          // will not be bubble up to presenter
          ...
       }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM