C# – Databinding in MVP winforms

cdata-bindingmvpwinforms

I have a WinForms application implemented in MVP. My form has a TextBox and I want to databind its Text property to a property in the Model. I don't want to refer to the Model in the View.

After searching in Google, I found that databinding by coupling Model and View is a bad idea. My sample initialization of Model, View and Presenter is as follows.

class View : Form, IView
{
    public View()
    {
        InitializeComponent();
        new Presenter(this);
    }
}

class Presenter
{
    public Presenter(IView) : this.Presenter(this, new Model())
    {
    }

    public Presenter(IView view)
    {
    }
}

class Model : IModel
{
    public Model()
    {
    }

}

At present I have 3 projects each for Model, View and Presenter. View has reference to Presenter and Presenter has reference to Model. Can anyone guide me how to form a databinding to a control in View to a property in Model?

EDIT

I know to do the things in Grid. We can assign Datasource property of grid to a List (or something similar) in presenter like:

_view.DataSource = _model.ListOfEmployees;

This will reflect the value in UI when ListOfEmployees changes in the Model. But what about a TextBox which exposes a Text property? How can I bind that in MVP architecture?

Best Answer

My recommendation is to encapsulate the View and Model in the Presenter. This means a specialized Presenter (in most cases) for a given View. In my opinion, this works out well since most Models will be different anyway.

class Presenter {
    readonly IView view;
    readonly IModel model;

    public Presenter() {
        // if view needs ref. to presenter, pass into view ctor
        view = new View(this);
        model = new Model();
    }

    // alternatively - with the model injected - my preference
    public Presenter(IModel Model) {
        // if view needs ref. to presenter, pass into view ctor
        view = new View(this);
        model = Model;
    }
}

In your IView, expose a control or control's data source property:

interface IView {
    object GridDataSource { get; set; }
}

Add to your Presenter some method:

void SetGridDatasource() {
    view.GridDatasource = model.SomeBindableData;
}

View implementation:

public object GridDatasource {
    get { return myGridView.DataSource; }
    set { myGridView.DataSource = value; }
}

Note:
Code snippets are untested and recommended as a starting point.

Update to comments:
INotifyPropertyChanged is a very valuable mechanism for updating properties between IView and IModel.

Most controls do have some sort of binding capability. I would recommend using those DataBinding methods whenever possible. Simply expose those properties through IView and let the Presenter set those bindings to the IModel properties.

Related Topic