2016-04-06 9 views
0

私は、コンストラクタ内CompositeCommandをインスタンス化し、次のViewModelを持っている:CompositeCommandの制御を反転するには?

public class ViewImportPreviewViewModel:BindableBase 
    { 
     private IEventAggregator eventAggregator; //event aggregator to enable Studio button in different ViewModel 

     private readonly IRegionManager regionManager; //region manager for navigation to the main menu 

     public CompositeCommand FinalizeImportClick{get;set;}//composite command to register multiple command for finalize import button click 


     public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) //constructor 
     { 
      this.eventAggregator = eventAggregator; 
      this.regionManager = regionManager; 

      FinalizeImportClick = new CompositeCommand(); 
      FinalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click 


     } 


     //subscriber method to the firs delegate command registered with finalize button click 
     private void NavigateToMain(string argument) 
     { 
      //it enables the studio button after import and sends it to the main menu view XAML 
      eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone"); 

      //it navigates to the main menu after import 
      regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

      //publish an event for the main buttons viewmodel and then over there try to fade in main buttons 
      eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone"); 
     } 


    } 

は今、私は制御の反転を行うには、クラスの外CompositeCommandをインスタンス化し、このようにユニティコンテナを通してそれを注入します:

public class ViewImportPreviewViewModel:BindableBase 
    { 
     private IEventAggregator eventAggregator; //event aggregator to enable Studio button in different ViewModel 

     private readonly IRegionManager regionManager; //region manager for navigation to the main menu 

     public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click 


     public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor 
     { 
      this.eventAggregator = eventAggregator; 
      this.regionManager = regionManager; 

      this.finalizeImportClick = finalizeImportClick; 
      finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click 


     } 


     //subscriber method to the firs delegate command registered with finalize button click 
     private void NavigateToMain(string argument) 
     { 
      //it enables the studio button after import and sends it to the main menu view XAML 
      eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone"); 

      //it navigates to the main menu after import 
      regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

      //publish an event for the main buttons viewmodel and then over there try to fade in main buttons 
      eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone"); 
     } 


    } 

、その後、モジュールの初期化に、私はこれを実行します。

CompositeCommand myCommand = new CompositeCommand(); 
    container.RegisterInstance<CompositeCommand>(myCommand); 

をIエラーは発生しませんが、コマンドが登録されても、NavigateToMain(string argument)は呼び出されません。

代わりにタイプを登録しようとしましたが、CompositeCommandはRegisterCommandメソッドの定義を含まないICommandインターフェイスを継承しています。

+1

は私の最初の質問は、あなたが最初の場所でこれを実行したいと思う理由は、ありますか?ユニットテストですか?ビューモデルの外で初期化したい理由が他にはありません。また、 'CompositeCommand'はシングルトンであり、作成されたすべてのビューで渡され、登録され、これによってコンポジットコマンドはあなたのviewmodelへの参照を保持するので、あなたの試みはかなり危険です。 'CompositeCommand'のライフタイムがアプリケーションのものと等しいので、ビューモデルはいつもガベージコレクションされません – Tseng

+0

正直言って、私は何か特別な理由はありませんこの。私はちょうど固体の原則に従おうとしていました。 – Ivan

答えて

2

実際、同じCompositeCommandに複数の疎結合モジュールが登録されるため、CompositeCommandsはシングルトン/静的であることが非常に一般的です。これは標準的であり、期待されています。

もちろん、ViewModelをテスト可能に保つためにこれを行う必要があります。あなたは、あなたの依存関係をctorで知りたいと思っています。あなたはあなたのVM内の静的メソッドを呼びたくない。

IApplicationCommandsのようなカスタムインターフェイスを作成し、公開する各CompositeCommandのプロパティを提供し、そのインターフェイスをコンテナに登録することを確認します。また、バインディングを参照することなくボタンをcompositeCommandsにバインドすることができるように静的バージョンを提供することをお勧めします。これは本当にいいです。

そのため、おそらくこのような何か:

//Create an interface to abstract away the implementation of the static GlobalCommands class 
public interface IGlobalCommands 
{ 
    CompositeCommand SaveAllCommand { get; } 
} 

public static class GlobalCommands 
{ 
    public static CompositeCommand SaveAllCommand = new CompositeCommand(); 
} 

//Create a facade around the static GlobalCommands class 
public class GloablCommandsFacade : IGlobalCommands 
{ 
    public CompositeCommand SaveAllCommand 
    { 
     get { return GlobalCommands.SaveAllCommand; } 
    } 
} 

そして、このように登録:

//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors 
     // and remove the call to a static class in our VM. This keeps us testable. 
     Container.RegisterType<IGlobalCommands, GloablCommandsFacade>(); 
関連する問題