8

在过去的几天里,我一直在使用 winforms 玩 MVP 模式,只有一件事我不知道该怎么做。如何从另一个视图创建子表单。这将是一个有效的选择。

 public class MyForm : IMainFormView
    {
        private MainFormPresenter pres;
        public MyForm() { pres = new MainFormPresenter(this); }

        //Event from interface.
        public event EventHandler<EventArgs> LoadSecondForm;

        public void SomeButtonClick()
        {
            LoadSecondForm(this, EventArgs.Empty);
        }
    }

    public class MainFormPresenter
    {
        private IMainFormView mView;

        public MainFormPresenter(IMainFormView view) {
            this.mView = view;
            this.Initialize();
        }

        private void Initialize() {
            this.mView.LoadSecondForm += new EventHandler<EventArgs>(mView_LoadSecondForm);
        }


        private void mView_LoadSecondForm(object sender, EventArgs e) {
            SecondForm newform = new SecondForm(); //Second form has its own Presenter.
            newform.Load(); // Load the form and raise the events on its presenter.
        }
    }

我主要关心如何使用此模式加载子表单,以及如何将 ID 从第一页传递给子表单。

谢谢。

4

3 回答 3

8

http://www.rickardnilsson.net/post/The-Humble-dialog-v2.aspx

上面的链接是我见过的最接近回答这个问题的链接。大多数解决这个问题的尝试都有待改进。

于 2009-06-30T20:23:30.143 回答
2

看看这个其他 SO question。虽然它与 WPF 而不是 WinForms 相关,但问题似乎是相同的。

本质上,我认为需要显示一个附属窗口一个服务(你可以称之为 WindowsService 或 DialogService 或类似的东西)。这可以帮助您正确看待事物,因为一旦您意识到这一点,依赖注入就会成为答案。

在您的回答中,您使用事件对此进行建模,但我更喜欢调用 DialogService 的 ShowDialog 方法的更明确的模型。然而,每种方法的机制并没有那么不同。

于 2009-07-04T19:36:18.030 回答
1

对此有几点评论

首先这个

    private void mView_LoadSecondForm(object sender, EventArgs e) {
        SecondForm newform = new SecondForm(); //Second form has its own Presenter.
        newform.Load(); // Load the form and raise the events on its presenter.
    }

如果您决定用 ThirdForm 代替 SecondForm,会发生什么?您需要找到每次调用 newform = new SecondForm 并进行更改。

相反,您应该将 SecondForm 的创建包装在命令对象中

   public class CreateSecondForm : ICommand
    {

        public void Execute() {
            SecondForm newform = new SecondForm(); //Second form has its own Presenter.
            newform.Load(); // Load the form and raise the events on its presenter.
        }

    }

然后在这里和任何其他地方提出第二种形式使用这种语法

private void mView_LoadSecondForm(object sender, EventArgs e) {
    CreateSecondForm createCmd = new CreateSecondForm(); 
    createCmd.Execute(); // Load the form and raise the events on its presenter.
}

如果您想用一个全新的表格代替 SecondForm,那么您只需要去一个地方。如果要传入状态或设置值,请使用命令的构造函数。您甚至可以传入另一个 Presenter 或 View 并让命令从其界面中提取信息。

我建议的另一件事是注册实现视图的表单,而不是使用新命令。这是在初始化期间完成的,并且注册表挂起您的主应用程序类。

例如。

public class MySecondForm : ISecondFormView, IViewForm
    {
        //Stuff ....
       Public ViewFormEnum ViewFormType {
          return ViewFormEnum.SecondForm;
       }
        //Stuff ....
    }

软件的其他地方

public void InitializeApp() {
        //Stuff ....
        MyApp.ViewForm.Add(new MySecondForm);

        //Stuff ....

}

然后命令是这样设置的。

   public class CreateSecondForm : ICommand
    {
        myApp theApp;
        public CreateSecondForm(myApp thisApp) {
           theApp = thisApp;
        }

        public void Execute() {
            SecondForm newform = theApp.Find(ViewFormEnum.SecondForm);
            if (newForm != null) 
               newform.Load(); // Load the form and raise the events on its presenter.
        }

    }

请原谅我的 C# 它不是我的主要语言。这种方法的优点是可以将包含表单的程序集换成具有不同表单集的不同程序集。这对于可以制作模拟类而不是表单的自动化测试特别有用。您还可以将其设置为处理空视图,这对于发布完整应用程序的子集很有用。

虽然我强烈建议您使用该命令来包装视图的创建。根据应用程序,注册 View 的第二个建议可能是矫枉过正。在我的 CAD/CAM 应用程序中,我有几十个对话框和几个不同的主要表单,用于设置和控制 2D 金属切割台的不同方面。然而,在我公司的一些其他应用程序中,我使用了一种简单的方法,因为它们大多是简单的实用程序。

于 2009-07-08T19:11:33.410 回答