【问题标题】:How is coordination of child views best handled in MVP?在 MVP 中如何最好地处理子视图的协调?
【发布时间】:2009-09-18 01:50:36
【问题描述】:

我正在尝试在 WinForms 中使用 MVP,但对如何最好地处理子视图之间的协调感到困惑。

例如,我有一个父视图,它有两个子视图。一个子视图上的事件需要导致第二个子视图采取行动。

父视图应该直接控制这个吗?看来我这样做是在绕过 MVP 模式。

或者子视图是否应该将彼此作为构造函数参数?在那种情况下,当第一个子视图触发事件时,第二个子视图会接收到该事件,然后通知其演示者发生了什么事?然后演示者需要从第一个子视图(它甚至不知道)获取数据,以便告诉第二个子视图要做什么。这似乎令人费解,所以我觉得我错过了一些东西。

下面是一些针对这种情况的伪代码:

public class ParentView : UserControl, IParentView
{
    private ChildViewOne childViewOne;
    private ChildViewTwo childViewTwo;
    private ParentViewPresenter presenter;

    private RegisterEvents()
    {
        childViewOne.EventOccured += new EventHandler(HandleEvent);
    }

    private void HandleEvent()
    {
        childViewTwo.DoSomething();
    }
}

【问题讨论】:

  • “一个子视图上的事件需要导致第二个子视图采取行动。”究竟发生了什么?
  • 例如,假设 childViewOne 是时间线,childViewTwo 是视频。时间线公开了一个 TimeChanged 事件,视频需要通过更改视频的当前帧来响应该事件。

标签: c# winforms model-view-controller user-interface mvp


【解决方案1】:

您可以查看Event Aggregator pattern。它将允许您保持一切松散耦合。 Prism 自带一个,它很容易使用,无需购买整个 Prism 框架/库。

您的代码可能如下所示:

public class ChildViewOne {
    private IEventAggregator evtAggregator;

    public ChildViewOne(IEventAggregator evtAggregator) {
        this.evtAggregator = evtAggregator;
    }

    private void OnEventOccured(){
        evtAggregator.GetEvent<EventOccured>().Publish();
    }
}

publish class ChildViewTwo {
    private IEventAggregator evtAggregator;

    public ChildViewTwo(IEventAggregator evtAggregator) {
     evtAggregator.GetEvent<EventOccured>().Subscribe(OnEventOccured);
    }

    private void OnEventOccured() {
        // Do something here...
    }
}

编辑:Brian Noyes 已将 prism 事件聚合器移植到 winforms。看看here, on his blog

【讨论】:

    【解决方案2】:

    在构造函数中获取其他子视图似乎是个坏主意。如果将来需要添加另一个子视图,您会怎么做?

    如果您通过父视图路由您的子事件会更好。如果您通过父视图路由事件,您如何违反 MVP?

    【讨论】:

    • 你的意思是像我目前正在做的那样,还是 ParentView 暴露了它的孩子的所有事件的联合,只是将这些事件传递给它的演示者?
    【解决方案3】:

    我将创建一个名为 SiblingView 的 IChildView 接口的属性(或者根据您的应用的业务上下文更合适的名称)。您甚至不必将它作为参数添加到构造函数中,而是让接口包含一个名为 SetSiblingView() 的方法。您可以从构造函数中调用它。然后你可以有一个事件 OnSiblingEventFired()。

    这对我来说似乎不那么令人费解,但也许这只是因为我过去通常是这样处理这类问题的。

    但我同意,在不了解父控件的太多细节的情况下,它似乎没有遵循 MVC 模式。

    【讨论】:

      猜你喜欢
      • 2021-06-16
      • 1970-01-01
      • 2010-11-24
      • 2020-10-03
      • 1970-01-01
      • 2013-06-13
      • 2014-01-28
      • 2014-09-02
      • 1970-01-01
      相关资源
      最近更新 更多