开发者

How to expose properties of a user control in .NET for the MVP pattern

开发者 https://www.devze.com 2023-04-09 07:47 出处:网络
I am implementing a simple UserControl that is actually a fancy TextBox. One of its features is that you can set a formatting specification and this formatting get\'s applied to its contents automatic

I am implementing a simple UserControl that is actually a fancy TextBox. One of its features is that you can set a formatting specification and this formatting get's applied to its contents automatically. For exa开发者_如何转开发mple, if you set the formatting specification to "000" and the contents are "42", then "042" will appear.

I am implementing this UserControl following the MVP pattern. The implementation is similar to this: how Implement usercontrol in winforms mvp pattern?. Also, check this question: passive view and display logic

Approach #1

My Title property in the View looks like this:

private string title;
public string Title {
    get { return title; }
    set { title = value; titleTextBox.Text = presenter.Format(title); }
}

It is my feeling that this implementation adds unnecessary coupling. For example, if I change the Presenter's Format method then I will have to go through all Views and change appropriately the call statement.

Approach #2

My Title property in the View looks like this:

public string Title {
    get { return presenter.Title; }
    set { presenter.Title = value; }
}

My Title property in the Presenter looks like this:

private string title;
public string Title {
    get { return title; }
    set { _view.SetTitle(this.Format(value); }
}

Now I have to add the SetTitle method in the View interface and in the View implementation:

public void SetTitle(string title) {
    titleTextBox.Text = title;
}

So, with this approach I get this ugly SetTitle Java-like method.

Approach #3

Instead of calling SetTitle create a new property RealTitle in the View and set that. It remains ugly with this Real prefix.

Your approach

Can you think of a better way?

Use case

The UserControl should be used like this:

var c = new FancyTextBox();
c.Format = "000";
c.Text = "42";
Controls.Add(c);

This snippet should display "042" inside the UserControl.

The big picture

Form            FancyTextBoxView             FancyTextBoxPresenter
  |                     |                              |
  |  ftb.Text = "42"    |                              |
  |-------------------->|                              |
  |                     |                              |
  |                     |              A               |
  |                     |----------------------------->|
  |                     |                              |
  |                     |              B               |
  |                     |<-----------------------------|

What are the A and B actions? I want the formatted text to appear in the UI. The formatting code is in the Presenter. The View has a titleTextBox that will hold the text in the UI.


Why don't you just define your View's Title property like this?

public string Title {
    get { return titleTextBox.Text; }
    set { titleTextBox.Text = value; }
}

There is absolutely no reason to define an additional SetTitle method. Also, in MVP, your view should never know about your Presenter.

Then whenever your Format function gets triggered, you can set the title of your view from there, for example:

void OnFormatCalled()
{
   _view.Title = FormatTitle(_view.Title);
}


I normally inject the View interface (and Model interface) into the Presenter. Now you have one place to worry about dependencies and testing.

Have your view fire an event when the title is set and have your Presenter subscribe to it. Then the Presenter can format the text and set the title on the view - the Presenter is in charge of the presentation of the view, the view just renders stuff. In this way the view is really dumb with little logic at all. This lends itself to being mocked out during unit testing and makes the presenter really easy to test.

Also notice how the formatting logic is also injected into the Presenter through a delegate property, thus decoupling the formatting from the presenter and making it changeable and testable. Just one way of doing it anyway...I like this approach.

public class Presenter
{
   private IView _view;
   private IModel _model;

   public Func<string, string> TitleFormatter { get; set; }

   public Presenter(IView view, IModel model)
   {
      _model = model;
      _view = view;

      _view.OnSetTitle += (s, e) => {
          _view.Title = TitleFormatter(e.Text);
       };
   }
}

public View : IView
{
    public event EventHandler<TitleChangedEventArgs> TitleChanged;

    public SomeUserActionEvent(object sender, SomeUserInterfaceEventArgs e)
    {
       TitleChanged(e.Text);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号