views:

287

answers:

5

Hi all,

I have a small application that I have written that uses the MVP pattern as follows:

  • I created an interface called IView
  • I implemented this interface in the Form
  • Passed in an instance of the form as type IView into the constructor of the presenter

The form contains a ListView component. The items that populates the ListView are created in the presenter. I heard that it is not a good idea to use UI component classes in the presenter. How and where should I create these ListViewItems? I could create the ListViewItems in the form itself but doesn't the form need to be as lightweight as possible with no logic in it?

Edit: N.B. This is a Windows Form application

+1  A: 

The ListViewItems are view specific so you should create them in the view. If you create them in the presenter all views must depend on ListViewItems which is not good.

Jakob Christensen
+1  A: 

Create data items in the presenter. Assign these to the view and have the view use data binding to display the data items:

//in presenter
var dataItems = _someService.GetData();
_view.Data = dataItems;

//in view code-behind
public ICollection<DataItem> Data
{
    get; set; //omitted for brevity - will require change notification
}

//in view XAML
<ListView ItemsSource="{Binding Data}">
  <ListView.View>
    <GridView>
      <GridViewColumn DisplayMemberBinding="{Binding Path=Name}"/> 
      <GridViewColumn DisplayMemberBinding="{Binding Path=Age}"/> 
    </GridView>
  </ListView.View>
</ListView>

HTH, Kent

Kent Boogaart
Hi Kent, this is a Windows Form application, sorry about that
Draco
lol - no problem. Same theory applies though. Presenter is agnostic of the UI and passes the data to the view. View can use binding or whatever to display the data.
Kent Boogaart
A: 

I recently had the same conundrum, but for a tree view.

To solve it nicely, you have to use delegates to handle the creation/conversion of data to visual elements.

Example:

class View
{
  TreeNode Builder(object foo, object bar) { ... }
}

class Presenter
{
  void InitView(View v)
  {
    Model.Build(v.Builder);
  }
}

Ok, that is very rough, but it allows you to quite easily build recursive structures like trees. :)

NOTE: the model and view does not actually care about eachother's types.

leppie
A: 

I could create the ListViewItems in the form itself but doesn't the form need to be as lightweight as possible with no logic in it?

A simple loop, and simple objects creation is not assumed to be difficult. Such code is fairly lilghtweight for a View:

class SomeView 
{
  void SetData(IEnumerable<DataItem> dataItems) 
  {
    foreach(DataItem dataItem in dataItems) 
    {
      ListViewItem lvi = new ListViewItem();
      lvi.Text = dataItem.Text;
      ...
    }
  }
}

Also, you can use Binding (as others suggested). This will simplify SetData even more.

Try too keep View code such simple that you can "validate" it by fast code review :-)

alex2k8
A: 

WinForms as technology is not designed for MVP, so a good idea of concern separating should be applied with reason. I would expect control in form, presenter should be free of view-specific things. Any control itself is breaking the mvp, because it contains data and representation. As your application will grow, it will be harder and harder to keep it MVP-style. There's no much benefit in implementing MVP. Usually, with WinForms traditional control-style (component-style) works good.

rudnev