0

Caliburn Micro を使用しており、起動時に表示されるログイン ビュー モデルがあります。

サーバーへのすべての接続を処理し、ViewModel への単純なコールバック イベントを提供する別のクラスを使用しています。これが ITransportClient です。

ユーザーが資格情報を入力してログインすると、ダイアログに接続プロセスがさまざまな状態 (接続、ユーザー名の検証、構成のダウンロード) に沿って表示されます。バックグラウンドで、Login ViewModel が を呼び出しITransportClient.Login()ます。

正常にログインし、すべての手順が完了すると、フォームが閉じて、メイン ウィンドウの ViewModel が開きます。資格情報が正しくないか、設定のダウンロードに問題がある場合は、エラーが表示され、ログイン フォームが残ります。

サーバーへの接続が失われた場合 (ITransportClient イベントで示されます)、アプリケーションは何度も再接続を試行し、サーバーが構成可能な期間オフラインのままである場合は、ログイン ウィンドウを再度表示する必要があります。

  1. 上記のフローに従って、ログイン ダイアログとメイン ウィンドウの間の切り替えをどのように処理するのが最善でしょうか?
  2. どうすればログイン ViewModel を閉じることができますIWindowManagerか?ShowDialogShowPopupShowWindow
  3. 上記を分離して、ログイン ビューモデルの外部でログイン ウィンドウを閉じ、ユーザーがメイン ウィンドウをログアウトしたときにログイン ウィンドウを表示できるようにする最善の方法は何ですか? これはブートストラップで行うべきですか、それとも別の ViewModel シェルを作成するべきですか?

私のブートストラッパー:

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);
        }
    }
}
4

1 に答える 1

1

CM はIWindowManagerインターフェイスを使用して、CM が理解できるウィンドウ管理の契約を提供します。実装自体は UI 固有のものです。たとえば、Telerik コントロールと Microsoft 標準コントロールは異なります。IWindowManagerとしてCMに実装されてWindowManagerおり、このマネージャーには、コントロール自体WindowConductorからのイベントを処理Windowし、ウィンドウに呼び出しを渡すという子クラスが含まれています(ビューモデルとビューコンテナーの間の接着剤)

見てみましょう:

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

このコンダクターはウィンドウを管理します。実装を見ると、 、IActivateIDeactivateなどの特定のインターフェースの存在をチェックしていることがわかりますIGuardClose。これらのインターフェイスを実装すると、ウィンドウにライフサイクル機能が追加されます。

Screen代わりにから継承するPropertyChangedBaseことは、これらのインターフェイスの実装を無料で取得する 1 つの方法です。また、IViewAware自動ビュー キャッシュを提供する実装と、ビューへの参照を取得するための便利なメソッドを取得することもできます。

このクラスから継承するか、インターフェイスを実装したら、メソッドを呼び出して VM 経由でウィンドウを閉じることができます ( などTryClose)。はWindowConductor必要な呼び出しをウィンドウ コントロールに渡しますIGuardClose。閉じる操作をキャンセルできるインターフェイスを使用して、ウィンドウが閉じないようにすることもできます。

ActionsVMにログイン方法があるように見えるので、CMですでにハンドルを持っていると思います。

今、これは回答の質問です-ポップアップウィンドウルートに行く必要がありますか? から継承しConductor<T>.Collections.OneActiveて呼び出すことができますActivateItem(yourViewModel)( Tcan be IScreen)。新しいアイテムがアクティブになると、ログインビューモデルは自動的に非アクティブになります。または、ログインに失敗したビューモデルまたはその同類を開くことができます。これは別のウィンドウを使用しませんが、実装は非常に簡単です。コンダクター ビューモデルにaContentControlをバインドするだけです。ActiveItem

詳細については、こちらをご覧ください (Simple MDI セクションとその周辺を参照してください)。

http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=ドキュメント

于 2012-12-04T00:18:22.273 に答える