Jeffers
Jeffers

Reputation: 183

MVP and rich user interface

I want to implement MVP pattern for my application. MVP Passive View actually. So I came to a problem, it's easy one, but can't decide which path should I take, so I want to ask you guru's, how to properly work with MVP and display rich UI.

I mean, let's assume we need to display some data, and customer wants it to be TreeView. There is requirement, that if user select different treenode, then the application updates itself with new data or something like that. At this point, i'm not sure how to implement View. (All view logic goes to presenter)

I don't think that it is a good idea, to expose WinForms class

ISomeForm : IView {
 //Presenter will take control of this TreeView.
 TreeView Host {
  get;
  }
}

or exposing my data models

ISomeForm : IView {
 //View knows how to display this data
 List<MyDataNodes> Items {
  get;
  set;
 }
}

or using other View interfaces.

ISomeForm : IView {
 //Presenter knows what Views presenter should display.
 List<IDataView> Items {
  get;
  set;
 }
}

Any suggestions?

Upvotes: 5

Views: 789

Answers (3)

Johann Gerell
Johann Gerell

Reputation: 25581

You should go more along the lines of the two latter examples; the view shouldn't expose WinForm-ish details to the presenter. See this answer for details on handling exactly your problem with TreeView updating - especially item 5.

Upvotes: 1

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112279

I had to solve this problem using a MVC pattern. You could expose the TreeView as you suggested in your first example. Then the presenter could subscribe some events of the TreeView. But if you go this way your presenter will probably have to subscribe a lot of events of differents controls on your form. I have chosen to have a single event on the form that sends messages to the controller (in my case). The messages are represented as a class and can have any information you need. This is how my message looks:

public class MvcMessage
{
    public object Source { get; private set; }
    public MessageType MessageType { get; private set; }
    public Type EntityType { get; private set; }

    public IList InvolvedItems { get; set; }
    public int NumAffected { get; set; }
    public EventArgs SourceEventArgs { get; internal set; }

    /// <summary>
    /// Name of property who changed its value. Applies to models implementing INotifyPropertyChanged.
    /// </summary>
    public string PropertyName { get; set; }

    public MvcMessage(object source, MessageType messageType, Type entityType)
    {
        this.Source = source;
        this.MessageType = messageType;
        this.EntityType = entityType;
    }

    public void Reroute(Type newEntityType)
    {
        MvcMessage reroutedMessage = (MvcMessage)MemberwiseClone();
        reroutedMessage.EntityType = newEntityType;
        Controller.NotifyAll(reroutedMessage);
    }
}

... where MessageType is a enum containing a lot of common commands and requests.

My IView interface then defines the event like this:

public delegate void ViewEventHandler(MvcMessage message);

public interface IView : IViewPage, IWin32Window
{
    event ViewEventHandler ViewEvent;
    ...
}

Upvotes: 1

Maxim V. Pavlov
Maxim V. Pavlov

Reputation: 10509

I would go with the View Interfaces.

In WPF MVVM, the more view separation I have, the easier it is to manage the UI/Logic interaction along the way.

Upvotes: 1

Related Questions