显示登录对话框,然后在与Caliburn Micro成功连接时显示主表单

时间:2012-12-02 20:20:45

标签: wpf mvvm caliburn.micro

我使用的是Caliburn Micro并且具有登录视图模型,该模型在启动时显示。

我正在使用一个单独的类来处理与服务器的所有连接,并为ViewModel提供简单的回调事件,这就是ITransportClient。

用户输入凭据,点击登录,对话框显示多个状态的连接过程(连接,验证用户名,下载配置)。在后台,Login ViewModel将调用ITransportClient.Login()

如果登录确定并且所有步骤都已完成,则表单应该关闭,主窗口ViewModel应该打开。如果凭据不正确或下载设置有问题,则应显示错误并保留登录表单。

如果服务器连接丢失(通过ITransportClient事件指示),则应用程序应尝试重新连接多次,如果服务器在可配置的时间段内保持脱机状态,则应再次显示登录窗口。

  1. 如何根据上述流程最好地处理登录对话框和主窗口之间的切换?
  2. 登录ViewModel如何关闭自己,我看到IWindowManager只有ShowDialogShowPopupShowWindow方法?
  3. 分离上述内容的最佳方法是什么,允许登录窗口在Login ViewModel外部关闭,以及当用户注销主窗口时显示登录窗口?这应该在引导程序中完成,还是应该为此创建单独的ViewModel shell?
  4. 我的引导程序:

    public class SimpleInjectorBootstrapper : Caliburn.Micro.Bootstrapper
    {
       private Container container;
    
       protected override void Configure()
       {
           this.container = new Container();
           this.container.Register<IWindowManager, WindowManager>();
           this.container.Register<IEventAggregator, EventAggregator>();
           this.container.Register<IAppViewModel, AppViewModel>();
           this.container.Register<ILoginViewModel, LoginViewModel>();
           this.container.RegisterSingle<ITransportClient, Transport.WCF.TransportClient>();
       }
    
       protected override object GetInstance(Type serviceType, string key)
       {
           return this.container.GetInstance(serviceType);
       }
    
       protected override IEnumerable<object> GetAllInstances(Type serviceType)
       {
           return this.container.GetAllInstances(serviceType);
       }
    
       protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
       {
           base.OnStartup(sender, e);
           var loginViewModel= this.container.GetInstance<ILoginViewModel>();
           var windowManager = this.container.GetInstance<IWindowManager>();
           windowManager.ShowWindow(loginViewModel);
       }
    }
    

    我的LoginView模型如下:

    public class LoginViewModel : PropertyChangedBase, ILoginViewModel
    {
        private readonly ITransportClient transportClient;
        private readonly IWindowManager windowManager;
        private string connectionStatus;
    
        public LoginViewModel(ITransportClient transportClient, IWindowManager windowManager)
        {
            this.transportClient = transportClient;
            this.windowManager = windowManager;
            this.transportClient.ConnectionEvent += new TransportConnectionEventHandler(UpdateStatusHandler);
        }
    
        public void Login()
        {
            // set from view, to be done via property, implement later
            var username = "test";
            var password = "test";
    
            var result = this.transportClient.Login(username, password);
    
            // if result is ok, we should close our viewmodel, however we 
            // cant call IWindowManager.Close(this) as only show methods exist
            // perhaps this is better handled elsewhere?
        }
    
        public void UpdateStatusHandler(string status)
        {
            this.ConnectionStatus = status;
        }
    
        public string ConnectionStatus
        {
            get
            {
                return this.connectionStatus;
            }
    
            set
            {
                this.connectionStatus = value;
                NotifyOfPropertyChange(() => ConnectionStatus);
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

CM使用IWindowManager接口提供CM可以理解的窗口管理合同。实现本身是UI特定的东西 - 例如Telerik控件与Microsoft标准控件=不同。 IWindowManager在CM中实现为WindowManager,此管理器包含一个名为WindowConductor的子类,其作用是处理来自Window控件本身的事件并将调用传递给窗口(它是viewmodel和views容器之间的粘合剂)

看看:

http://caliburnmicro.codeplex.com/SourceControl/changeset/view/35f41b2f9113#src%2fCaliburn.Micro.Silverlight%2fWindowManager.cs

此指挥为您管理窗口 - 如果查看实现,您可以看到它检查是否存在某些接口,例如IActivateIDeactivateIGuardClose。如果您实现这些接口,您的窗口将获得更多生命周期功能。

继承Screen而不是PropertyChangedBase是免费获得这些接口实现的一种方法,您还可以获得IViewAware的实现,它提供了自动视图缓存和一个有用的方法来获取参考视图

从此类继承或实现接口后,您可以调用方法通过VM关闭窗口(例如TryClose)。 WindowConductor将负责将必要的调用传递给窗口控件,甚至可以使用允许您取消关闭操作的IGuardClose接口阻止窗口关闭。

我假设您已经在CM中拥有Actions句柄,因为您似乎在VM上有登录方法。

现在这是一个答案中的问题 - 你需要进入弹出窗口路线吗?您可以继承Conductor<T>.Collections.OneActive并致电ActivateItem(yourViewModel)T可以是IScreen)。激活新项目时,您的登录视图模型将自动停用,或者您可以打开登录失败的视图模型或类似的东西。虽然这不使用单独的窗口,但实现非常简单,只需在导体视图模型上绑定ContentControlActiveItem

请查看详细信息(查看简单MDI部分及其周围):

http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation