2012-10-18 42 views
3

已经学习了MVP并尝试在WinForms中使用它来编写测试应用程序。我正在努力寻找一个关于如何在我的表单/视图之间导航的很好解释的示例。作为一个例子,程序启动,我想显示一个登录对话框,然后进入我的主视图,如果登录成功。目前,我的Main方法看起来像这样:WinForms中的MVP导航

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)的包装。事情是,我读过我不应该通过注入器手动创建实例,因为它们应该通过构造器注入完成。

我已经设法做到了这一点,但没有涉及到导航。我想不出一种优雅的方式来解读我的观点,并想知道这里有没有人可以对此有所了解?我在应用程序控制器上阅读了一些内容,但没有找到清楚显示它的示例。

+0

'mainView'可能有一些方法来显示视图.. – dotNETbeginner

+0

您可以在mainView中插入一个方法,该方法返回实际的窗体。 – Rockstart

+0

这对我来说看起来不像MVP,你应该在Presenter中放置逻辑。 –

回答

3

关于导航问题:

我已经设法做到了这一点,但没有涉及到 导航。我想不出一种优雅的方式来通过我的观点 ,并想知道这里的任何人是否可以阐明这一点?我在应用程序控制器上读了一点 ,但没有找到一个示例 来清楚地显示它。

下面是我用过的结构的简化版本。请注意,调用NavigateTo方法时会自动调用设置和拆卸钩子。此外,+1 @ @AlexBurtsev,他的回答暗示了这种方法。

// 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 
    } 

} 
1

可以在MAINVIEW插入一个方法,它返回的实际form.Then你可以叫

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

在主可以打电话,

Application.Run(mainView.GetView()) 
2

我还没有使用的WinForms久时间,但我会尽力回答这个问题。我会使用与WPF Prism相同的策略。

关于MainView和Application.Run: 创建一个主要区域(根表单),其中容器内部可以容纳UserControl(我忘了确切的类名),然后当你需要切换根视图时,你做RootView。 SetView(UserControl视图),它将执行类似Form.Clear(),Form.AddChild(view)的操作。

关于导航和使用容器: 您可以创建用于导航的服务:您在构造函数中包含INavigationService.NavigateView方法注入INavigationService(字符串(或类型)的viewName,params对象[] additionalData)

+0

谢谢。在看过tcarvin的回答后,我可以看到你在说什么。 – woodstock