MVP,Winforms - 事件处理程序和代理

时间:2012-04-30 22:08:51

标签: c# winforms mvp

我在一些使用被动视图的WinForms应用程序中实现了MVP模式。我以Action<的形式实现了一个包含属性和委托的接口。 T>和Func< T>在具体视图中连接UI事件并回调给演示者。

我即将开始一个新项目并对在线模式进行了一些研究,包括这里的模式的许多示例,并注意到所有使用EventHandler通知演示者。

我真的不明白为什么会在这种情况下使用事件,因为我看到一个视图只有一个演示者。

我的问题是,这是为了与.Net框架如何使用事件保持一致,还是出于我没有看到的其他原因?

这是我使用的模式的一个简单例子:

public interface IViewAbstraction
{
    public ModelData ModelData { set; }
    public Action<ModelData> ModelDataChangedCallback { set; }
}

public class SomeWinForm : Form, IViewAbstraction
{
    private Action<ModelData> modelDataChanged;
    private ModelData model;

    public ModelData ModelData
    {
        set { /* when this property changes, update UI */ }
    }

    public Action<ModelData> ModelDataChangedCallback
    {
        set { modelDataChanged = value; }
    }

    private void OnSomeWinformsEvent(EventArgs args)
    {
        if (modelDataChanged == null) throw new Exception();

        modelDataChanged(model);
    }
}

public class Presenter
{
    private readonly IViewAbstraction view;
    private readonly IDataLayerAbstraction dataLayer;

    public Presenter(IViewAbstraction view, IDataLayerAbstraction dataLayer)
    {
        this.dataLayer = dataLayer;
        this.view = view;
        this.view.ModelDataChangedCallback = OnModelChanged;
        this.view.ModelData = dataLayer.GetData();
    }

    private void OnModelChanged(ModelData data)
    {
        // validate and save data.
    }
}

1 个答案:

答案 0 :(得分:4)

您的模式与使用事件基本相同,但有一个关键区别。事件不公开底层委托(在您的示例中为ModelDataChangedCallback)。公开此操作是不好的做法,因为其他代码可以清除调用列表。一个事件将有一个底层委托,可以添加或删除,但永远不会从该类的范围之外清除。

我不明白你没有多个订阅者的观点 - 这不是不使用事件的理由。事件只是一个类说“嘿!事情已经发生”的一种方式,与Presenter对象的一对一映射是完全合理和正常的。

你也不会在视图中看到那个看起来很奇怪的只写属性。