Monday, April 11, 2011

Where should I create ListViewItem list when using the MVP pattern?

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

From stackoverflow
  • 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.

  • 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

    Draco : Hi Kent, this is a Windows Form application, sorry about that
    Kent Boogaart : 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.
  • 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.

  • 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 :-)

  • 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.

0 comments:

Post a Comment