2012-01-31 4 views
4

メニューアイテムを介してWPFフォームを開く(大規模な)従来のWinFormsアプリケーションがあります。このWPFフォームはInfragisticsグリッドといくつかのボタン/ドロップダウンをホストします。1つのWPFフォームを持つWinFormsアプリケーションでCaliburn Microを使用する方法

この孤立したWPFフォームは、WPFへの移行の初期段階を表します。その後、アプリのより多くのコンポーネントがWPFに移行し、最終的にはアプリ全体が移動します。

マイグレーションの一環として、Caliburn Microを使用したいと考えています。したがって、この孤立したWPFフォームで使用することができればいいと思います。

  • 誰かが、WPFフォームでCaliburn Microを使用する方法についてのいくつかの指針を提供できますか?
  • なぜ、Caliburn Microを使用するのが理にかなっていないのかもしれませんか?

私がこれまでに読んだドキュメントには、上記のシナリオではなく、アプリケーションが目的のルートビューモデルで確実に起動するブートストラッパーが含まれています。

多くの感謝!ここで

+0

この場合、C.M.あなたが解決するよりも多くのトラブルを引き起こします。 CM。幅広い/自動化されたMVVMフレームワークを使用して、純粋なWPFアプリケーションの「起動と実行」を高速化することを目的としています。あなたのアプリケーションは、フレームワークからビルドの段階を過ぎており、この段階で新しいものを導入することは非常に困難です。 WPVに移行するために、堅実なMVVM(厳しい方法)を適用するのに最も役立つものは何でしょうか。プロジェクトはWinFormsに入っているので、まともなMVC実装で構築されているチャンスはゼロではないため、MVVMへの移行はそれほど苦労しないかもしれません。がんばろう! – EtherDragon

答えて

5

多くのGoogle検索とCaliburn Microのソースコードを経て、私はサンプルテストアプリケーションで動作するアプローチを考え出しました。私はいくつかの理由でここにテストアプリケーションを投稿することはできませんが、ここでは簡単なアプローチです。

  • ボタンを使用してWinFormを作成します。ボタンのクリックで
  • は、ChildWinFormの負荷ハンドラでChildWinForm
  • を示しています。

    
    // You'll need to reference WindowsFormsIntegration for the ElementHost class 
    // ElementHost acts as the "intermediary" between WinForms and WPF once its Child 
    // property is set to the WPF control. This is done in the Bootstrapper below.  
    var elementHost = new ElementHost{Dock = DockStyle.Fill}; 
    Controls.Add(elementHost); 
    new WpfControlViewBootstrapper(elementHost); 
    
  • 上記のブートストラップは、あなたが記述する必要がありますものです。

  • Customizing the BootstrapperCaliburn Microdocumentationから参照してください。
  • この投稿の目的上、Caliburn Bootstrapperクラスから派生させてください。
  • それはそのコンストラクタで、次の操作を行う必要があります。バインド:

    
    // Since this is a WinForms app with some WPF controls, there is no Application. 
    // Supplying false in the base prevents Caliburn Micro from looking 
    // for the Application and hooking up to Application.Startup 
    protected WinFormsBootstrapper(ElementHost elementHost) : base(false) 
    { 
        // container is your preferred DI container 
        var rootViewModel = container.Resolve(); 
        // ViewLocator is a Caliburn class for mapping views to view models 
        var rootView = ViewLocator.LocateForModel(rootViewModel, null, null); 
        // Set elementHost child as mentioned earlier 
        elementHost.Child = rootView; 
    } 
    
  • 注意すべき最後の事はあなたがCALを設定する必要がありますということです。WpfControlViewのXAMLのモデル依存プロパティ。

    
    cal:Bind.Model="WpfControls.ViewModels.WpfControl1ViewModel" 
    
  • 依存関係プロパティの値は、WpfControlViewModelを解決するためにそれを使用する必要がありBootstrapper.GetInstance(タイプサービス種別、文字列キー)に文字列として渡さ使用されます。

  • 私が使用するコンテナ(Autofac)は文字列のみの解像度をサポートしていないので、プロパティをビューモデルの完全修飾名に設定することを選択しました。この名前は、型に変換してコンテナから解決するために使用できます。
+0

ViewModelBinder.Bind(rootViewModel、rootView、null)を使用できます。 calの代わりにViewLocator.LocateForModelの後:Bind.Model – Anders

1

はあなたのviewmodelsを作成し、CMのフレームワークが提供PropertyChangedBaseクラスからそれらを継承

  • で始めることができます代です。
  • 必要に応じて、緩やかに結合されたコミュニケーション\統合のためのEventAggregatorのインパネレーションを使用してください。
  • ルートビューモデルを定義する汎用実装なしでAppBootStrapperを実装します。

ビューの最初のアプローチを使用して、ビューにBind.Model添付プロパティを使用してビューをモデルにバインドできます。私は、アプローチhereを記述するサンプルアプリケーションを作成しました。

2

受け入れ答えにフォローアップ、私はそのようにして、どのようにViewModelにファースト・アプローチにWinFormsのブートストラップを実装する方法を紹介したいと思います(良いもの!):あなたが勝った

  1. ビュー内から直接ViewModelにバインドする必要はありません。このため

我々は(あなたのケースに該当する場合)ウィンドウ上Showメソッドを呼び出し、そして結合が起こることを可能にしていないことを確認し、ウィンドウマネージャの私たち自身のバージョンを作成する必要があります。

public class WinformsCaliburnBootstrapper<TViewModel> : BootstrapperBase where TViewModel : class 
{ 

    private UserControl rootView; 

    public WinformsCaliburnBootstrapper(ElementHost host) 
     : base(false) 
    { 
     this.rootView = new UserControl(); 
     rootView.Loaded += rootView_Loaded; 
     host.Child = this.rootView; 
     Start(); 
    } 

    void rootView_Loaded(object sender, RoutedEventArgs e) 
    { 
     DisplayRootViewFor<TViewModel>(); 
    } 

    protected override object GetInstance(Type service, string key) 
    { 
     if (service == typeof(IWindowManager)) 
     { 
      service = typeof(UserControlWindowManager<TViewModel>); 
      return new UserControlWindowManager<TViewModel>(rootView); 
     } 
     return Activator.CreateInstance(service); 
    } 

    private class UserControlWindowManager<TViewModel> : WindowManager where TViewModel : class 
    { 
     UserControl rootView; 

     public UserControlWindowManager(UserControl rootView) 
     { 
      this.rootView = rootView; 
     } 

     protected override Window CreateWindow(object rootModel, bool isDialog, object context, IDictionary<string, object> settings) 
     { 
      if (isDialog) //allow normal behavior for dialog windows. 
       return base.CreateWindow(rootModel, isDialog, context, settings); 

      rootView.Content = ViewLocator.LocateForModel(rootModel, null, context); 
      rootView.SetValue(View.IsGeneratedProperty, true); 
      ViewModelBinder.Bind(rootModel, rootView, context); 
      return null; 
     } 

     public override void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null) 
     {    
      CreateWindow(rootModel, false, context, settings); //.Show(); omitted on purpose     
     } 
    } 
} 

私はこれが同じニーズを持つ人の役に立てば幸い:

はここで完全なコードです。それは確かに私を救った。

関連する問題