3

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

我正在UserControl按照 MVP 模式实现这一点。实现类似这样:如何在winforms mvp模式中实现usercontrol?. 另外,检查这个问题:被动视图和显示逻辑

方法#1

我的Title财产View如下所示:

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

我觉得这个实现增加了不必要的耦合。例如,如果我更改Presenter'Format方法,那么我将必须遍历所有Views 并适当地更改 call 语句。

方法#2

我的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方法:ViewView

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

因此,通过这种方法,我得到了这种丑陋SetTitle的类似 Java 的方法。

方法#3

而不是调用在中SetTitle创建一个新属性并设置它。这个前缀仍然很难看。RealTitleViewReal

你的方法

你能想出更好的方法吗?

用例

UserControl应该这样使用:

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

此代码段应显示"042"UserControl.

大图

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

A 和 B 动作是什么?我希望格式化的文本出现在 UI 中。格式代码在Presenter. View有一个将titleTextBox在 UI 中保存文本的。

4

2 回答 2

2

你为什么不像这样定义你的 View 的 Title 属性呢?

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

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

然后,每当您的 Format 函数被触发时,您就可以从那里设置视图的标题,例如:

void OnFormatCalled()
{
   _view.Title = FormatTitle(_view.Title);
}
于 2011-09-30T12:47:36.413 回答
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);
    }
}
于 2011-09-30T12:50:29.290 回答