3

一直在学习 MVP,并尝试在 WinForms 中使用它编写测试应用程序。我正在努力寻找一个解释清楚的示例,说明如何在我的表单/视图之间导航。例如,程序启动,我想显示一个登录对话框,如果登录成功则进入我的主视图。目前,我的 Main 方法如下所示:

static void Main()
{
   var loginView = Injector.Resolve<ILoginView>();
   if (loginView.DoLogin() != LoginResult.OK) return;
   var mainView = Injector.Resolve<IMainView>();
   Application.Run(mainView); // won't work as mainView isn't a form
}

Injector 对象只是一个 IoC 工具(目前是 StructureMap)的包装器。问题是,我读过我不应该通过 Injector 手动创建实例,因为它们应该通过构造函数注入来完成。

我已经设法做到了这一点,但在导航方面却没有。我想不出一种优雅的方式来浏览我的观点,并且想知道这里是否有人可以对此有所了解?我已经阅读了一些关于应用程序控制器的内容,但没有找到一个可以清楚地展示它的示例。

4

3 回答 3

3

关于导航问题:

我已经设法做到了这一点,但在导航方面却没有。我想不出一种优雅的方式来浏览我的观点,并且想知道这里是否有人可以对此有所了解?我已经阅读了一些关于应用程序控制器的内容,但没有找到一个可以清楚地展示它的示例。

下面是我使用的构造的简化版本。请注意,调用该NavigateTo方法时会自动调用 setup 和 tear down 挂钩。另外,对@AlexBurtsev +1,因为他的回答暗示了这种相同的方法。

// Presenter can and should offer common services for the
// subclasses 
abstract class Presenter
{

   public void Display()
   {
      OnDisplay();
   }

   public void Dismiss()   
   {
      OnDismiss();
   }


   protected virtual OnDisplay() // hook for subclass
   {   
   }

   protected virtual OnDismiss() // hook for subclass
   {   
   }

   private NavigationManager _navMgr;

   internal NavigationMgr NavigationManager
   {   
      get
      {
         return _navMgr;
      }
      set
      {
         _navMgr = value;
      }

   }

}

// NavigationManager is used to transition (or navigate) 
// between views
class NavigationManager
{

   Presenter _current;

   // use this override if your Presenter are non-persistent (transient)
   public void NavigateTo(Type nextPresenterType, object args)
   {   
      Presenter nextPresenter = Activator.CreateInstance(nextPresenterType);   
      NavigateTo(nextPresenter);   
   }

   // use this override if your Presenter are persistent (long-lived)
   public void NavigateTo(Presenter nextPresenter, object args)
   {
      if (_current != null)
      {
         _current.Dismiss()
         _current.NavigationMgr = null;
         _current = null;
      }

      if (nextPresenter != null)
      {
         _current = nextPresenter;
         _current.NavigationMgr = this;
         _current.Display(args);
      }         
   }

}


class MainMenuPresenter : Presenter
{

   private IMainMenuView _mainMenuView = null;

   // OnDisplay is your startup hook
   protected override void OnDisplay()
   {
      // get your view from where ever (injection, etc)
      _mainMenuView = GetView();      

      // configure your view
      _mainMenuView.Title = GetMainTitleInCurrentLanguage();
      // etc      
      // etc

      // listen for relevent events from the view
      _mainMenuView.NewWorkOrderSelected += new EventHandler(MainMenuView_NewWorkOrderSelected);

      // display to the user
      _mainMenuView.Show();
   }

   protected override void OnDismiss()
   {
      // cleanup
      _mainMenuView.NewWorkOrderSelected -= new EventHandler(MainMenuView_NewWorkOrderSelected);
      _mainMenuView.Close();
      _mainMenuView = null;
   }

   // respond to the various view events
   private void MainMenuView_NewWorkOrderSelected(object src, EventArgs e)
   {
      // example of transitioning to a new view here...
      NavigationMgr.NavigateTo(NewWorkOrderPresenter, null);            
   }

}


class NewWorkOrderPresenter : Presenter
{

   protected override void OnDisplay()
   {
      // get the view, configure it, listen for its events, and show it
   }

   protected override void OnDismiss()
   {
      // unlisten for events and release the view
   }

}
于 2012-10-23T12:38:18.880 回答
2

好久没用过WinForms了,试着回答一下。我会使用与 WPF Prism 相同的策略。

关于 MainView 和 Application.Run:创建一个主区域(根窗体),里面有一个空容器,里面可以容纳 UserControl(我忘了确切的类名),然后当你需要切换根视图时,你做 RootView.SetView(UserControl view)它将执行诸如 Form.Clear()、Form.AddChild(view) 之类的操作。

关于导航和使用容器:您可以创建一个导航服务:INavigationService,您可以使用 INavigationService.NavigateView(String(or Type) viewName, params object[] additionalData) 等方法将其注入构造函数

于 2012-10-19T06:40:46.100 回答
1

您可以在 mainView 中插入一个返回实际表单的方法。然后您可以调用

Mainview:IMainView 
{
        Form GetView()
        {
              //return new Form();
        }
 }

在 Main 你可以调用,

Application.Run(mainView.GetView())
于 2012-10-19T05:06:08.200 回答