如何在.NET中为MVP模式公开用户控件的属性

时间:2011-09-30 12:42:09

标签: .net user-controls mvp passive-view

我正在实施一个简单的UserControl,实际上是一个花哨的TextBox。它的一个功能是您可以设置格式规范,并且此格式自动应用于其内容。例如,如果您将格式规范设置为"000"且内容为"42",则会显示"042"

我正在按照MVP模式实现此UserControl。实现类似于:how Implement usercontrol in winforms mvp pattern?。另外,请检查此问题:passive view and display logic

方法#1

Title中的View属性如下所示:

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

我觉得这种实现增加了不必要的耦合。例如,如果我更改了Presenter的{​​{1}}方法,那么我将不得不浏览所有Format并正确更改调用语句。

方法#2

View中的Title属性如下所示:

View

public string Title { get { return presenter.Title; } set { presenter.Title = value; } } 中的Title属性如下所示:

Presenter

现在我必须在private string title; public string Title { get { return title; } set { _view.SetTitle(this.Format(value); } } 界面和SetTitle实施中添加View方法:

View

所以,通过这种方法,我得到了这种丑陋的public void SetTitle(string title) { titleTextBox.Text = title; } 类Java方法。

方法#3

而不是调用SetTitleSetTitle中创建新属性RealTitle并设置它。这个View前缀仍然很难看。

您的方法

你能想到一个更好的方法吗?

用例

Real应该像这样使用:

UserControl

此代码段应在var c = new FancyTextBox(); c.Format = "000"; c.Text = "42"; Controls.Add(c); 内显示"042"

大图

UserControl

A和B的行动是什么?我希望格式化的文本出现在UI中。格式代码位于Form FancyTextBoxView FancyTextBoxPresenter | | | | ftb.Text = "42" | | |-------------------->| | | | | | | A | | |----------------------------->| | | | | | B | | |<-----------------------------| Presenter有一个View,用于保存用户界面中的文字。

2 个答案:

答案 0 :(得分:2)

为什么不直接定义View的Title属性?

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

绝对没有理由定义额外的SetTitle方法。此外,在MVP中,您的视图永远不会知道您的演示者。

然后,只要触发了Format函数,就可以从那里设置视图的标题,例如:

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

答案 1 :(得分:1)

我通常将View界面(和Model界面)注入Presenter。现在你有一个地方担心依赖和测试。

在设置标题并让Presenter订阅它时,让您的视图触发事件。然后,Presenter可以格式化文本并在视图上设置标题 - Presenter负责视图的表示,视图只是呈现内容。通过这种方式,视图真的很愚蠢,几乎没有逻辑。这有助于在单元测试期间被模拟,并使演示者非常容易测试。

还要注意格式化逻辑如何通过委托属性注入到Presenter中,从而将格式与演示者分离并使其可更改和可测试。无论如何只是一种方式...我喜欢这种方法。

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);
    }
}