C# 如何在MVP被动视图中显示复杂数据

C# 如何在MVP被动视图中显示复杂数据,c#,winforms,design-patterns,mvp,C#,Winforms,Design Patterns,Mvp,我研究MVP模式已经有一段时间了,并设法创建了一些简单的符合MVP的应用程序 我现在正试图将该模式应用到更复杂的应用程序中,我对实现这一点的最佳方法有些怀疑 我的应用程序只有一个WinForm,有两个按钮用于加载两种不同类型的数据。我的视图界面如下所示: interface IView_MainForm { // Load input // event EventHandler<InputLoadEventArgs> LoadInput_01; ev

我研究MVP模式已经有一段时间了,并设法创建了一些简单的符合MVP的应用程序

我现在正试图将该模式应用到更复杂的应用程序中,我对实现这一点的最佳方法有些怀疑

我的应用程序只有一个WinForm,有两个按钮用于加载两种不同类型的数据。我的视图界面如下所示:

interface IView_MainForm
{
    //  Load input
    //
    event EventHandler<InputLoadEventArgs> LoadInput_01;
    event EventHandler<InputLoadEventArgs> LoadInput_02;

    bool Input01_Loaded { get; set; }
    bool Input02_Loaded { get; set; }
}
接口IView\u主窗体
{
//负载输入
//
事件处理程序LoadInput_01;
事件处理程序LoadInput_02;
bool Input01_加载{get;set;}
bool Input02_加载{get;set;}
}
IView通过构造函数注入在我的演示者中引用:

public Presenter_MainForm(IView_MainForm view)
{
    this.View = view;
    this.View.LoadInput_01 += new EventHandler<InputLoadEventArgs>(OnLoadInput_01);
    this.View.LoadInput_02 += new EventHandler<InputLoadEventArgs>(OnLoadInput_02);
}
public Presenter\u MainForm(IView\u MainForm视图)
{
这个视图=视图;
this.View.LoadInput_01+=新的事件处理程序(OnLoadInput_01);
this.View.LoadInput_02+=新的事件处理程序(OnLoadInput_02);
}
到目前为止,一切顺利。当用户单击加载数据的两个按钮中的任何一个按钮时,将引发LoadInput_u###事件,演示者正在处理它,检查输入是否存在错误,并根据我的数据模型构造它

我的下一步将在视图中显示处理后的数据

我正在努力使我的视图尽可能被动和“愚蠢”,假设它对演示者一无所知(它不订阅它的事件,演示者通过调用IView方法将数据发送到视图),更不用说模型了

如果视图不知道数据模型是什么样子,我应该如何填充像TreeView这样的控件


另外,我是否正确地理解了MVP的全部内容,或者我遗漏了什么?

视图中使用
复杂类型属性没有什么错。假设您有一些
ComplexType

class ComplexType
{
   public string ParentNode {get;set;}
   public List<string> ChildNodes {get;set;}
   // some other properties
}
由于您的
模型
用于有2个输入的
视图
,因此您的模型可能看起来像这样

public interface IModel
{
   public ComplexType Input01Data {get;set;}
   public ComplexType Input02Data {get;set;}
}
现在,在您的
演示者中
只需处理从
视图
触发的事件,填充
模型
并在
视图
上设置属性即可

class Presenter
{
    private IModel _myModel...
    private IRepository _repository;
    public Presenter(IView_MainForm view, IRepository repository)
    {
        _repository = repository;
        this.View = view;
        this.View.LoadInput_01 += new EventHandler<InputLoadEventArgs>(OnLoadInput_01);
        this.View.LoadInput_02 += new EventHandler<InputLoadEventArgs>(OnLoadInput_02);
    }

    public void OnLoadInput_01(object sender, InputLoadEventArgs e)
    {
         // get data based on passed arguments (e.SomeProperty)
         // construct IModel
         myModel = _repository.GetData(e.SomeProperty);
         // pass data to IView_MainForm
         View.SetInput01Data(myModel.Input01Data);
     }
}

我已经编辑了你的标题。请参见“”,其中一致意见是“不,他们不应该”。您的视图(表单)是否实现了
IView\u main表单
?如果您的
视图
不知道
数据模型是什么(我假设您的意思是
模型
),它应该如何将自身绑定到数据?@JohnSaunders,明白了,谢谢@huMptyduMpty,是的,我的视图(
MainForm
)实现了
IView\u MainForm
,这就是我现在能够在基本级别实现MVP模式的方式:
Presenter
IView\u MainForm
作为其构造函数中的参数,订阅其事件并通过调用接口中指定的方法(并由
MainForm
实现)显示结果。@michaelmoore这正是问题所在。据我所知,在MVP(PV)
视图
模型
中,由于是
演示者
处理用户事件,并指示
视图
如何显示数据,因此它们彼此一无所知。如果我的
视图
已经知道我的数据是什么样子的,那么MVP的首要意义是什么?然后,我可以通过直接引用我的
模型
来填充我的控件。。。我是不是遗漏了什么?
class Presenter
{
    private IModel _myModel...
    private IRepository _repository;
    public Presenter(IView_MainForm view, IRepository repository)
    {
        _repository = repository;
        this.View = view;
        this.View.LoadInput_01 += new EventHandler<InputLoadEventArgs>(OnLoadInput_01);
        this.View.LoadInput_02 += new EventHandler<InputLoadEventArgs>(OnLoadInput_02);
    }

    public void OnLoadInput_01(object sender, InputLoadEventArgs e)
    {
         // get data based on passed arguments (e.SomeProperty)
         // construct IModel
         myModel = _repository.GetData(e.SomeProperty);
         // pass data to IView_MainForm
         View.SetInput01Data(myModel.Input01Data);
     }
}
[Test]
public void ShouldLoadInput01DataOnButtonClick()
{
   // Arrange
   IModel data = // create dummy data

   Mock<IView_MainForm> clientsViewMock = new  Mock<IView_MainForm>();
   Mock<IRepository> clientsRepositoryMock = new Mock<IRepository>();

   clientsRepositoryMock.Setup(repository => repository.GetData(something)).Returns(data.Input01Data);     
   var presenter = new Presenter(clientsViewMock.Object, clientsRepositoryMock .Object);

   // Act
   clientsViewMock.Raise(view => view.LoadInput01 += null, new InputLoadEventArgs());

   // Assert
   clientsViewMock.Verify(view => view.SetInput01Data(data.Input01Data), "Input01 data expected be set on button click.");
}