2017-05-20 12 views
0

(TLDRバージョンは以下です。)私はMEFをIoC、Caliburn MicroをフレームワークとしてWPFアプリケーションを設計しています。アプリケーションのメインウィンドウは次のようである:ここではCaliburn MicroのスクリーンコンダクターでMEFを使用する

Main Window

のViewModelはウィンドウのためです:

[Export(typeof(MainViewModel))] 
class MainViewModel : Conductor<PropertyChangedBase>, IHandle<ViewModelType> 
{ 
    private readonly IEventAggregator _eventAggregator; 

    private IEnumerable<Screen> _screenList { get; set; } 

    [ImportingConstructor] 
    public MainViewModel(IEventAggregator eventAggregator, [ImportMany]IEnumerable<Screen> screenList) 
    { 
     _screenList = screenList; 
     _eventAggregator = eventAggregator;      
     _eventAggregator.Subscribe(this); 
     ShowMenu(); 
    } 

    public void Handle(ViewModelType message) 
    {   
     ActivateItem(_screenList.FirstOrDefault(c => c.GetType() == message.VMtype)); 
     DisplayName = "B.I. Surgical & Dressing - " + (ActiveItem as Screen)?.DisplayName; 
     NotifyOfPropertyChange(() => CanShowMenu); 
    } 

    public void ShowMenu() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(Menu.MenuViewModel))); 
    public bool CanShowMenu => ActiveItem.GetType() != typeof(Menu.MenuViewModel); 
} 

ので、_screenListが表示される必要があるすべての画面が含まれており、ここにあります表示するViewModelを示すイベントを発行するMenuViewModel:

[Export(typeof(MenuViewModel))] 
[PartCreationPolicy(CreationPolicy.NonShared), Export(typeof(Screen))] 
class MenuViewModel : Screen 
{ 
    private readonly IEventAggregator _eventAggregator;   

    [ImportingConstructor] 
    public MenuViewModel(IEventAggregator eventAggregator) 
    { 
     _eventAggregator = eventAggregator; 
     DisplayName = "Menu"; 
    } 

    public void CreateInvoice() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(Invoice.InvoiceViewModel))); 
    public void EnterPaymentsReceived() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(ReceivedPayments.PaymentsReceivedViewModel))); 
    public void EnterPurchases() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(PurchaseDetails.PurchaseDetailsViewModel))); 
    public void AddClientAndRates() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(AddClient.AddClientViewModel))); 
    public void EditClientAndRates() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(EditClient.EditClientViewModel))); 
    public void AddItem() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(AddItem.AddItemViewModel))); 
    public void EditItems() => _eventAggregator.PublishOnUIThread(new ViewModelType(typeof(EditItem.EditItemViewModel))); 

} 

ただし、私は問題です私がMenuViewModelのボタンをクリックしたときに新しいVMを取得するのではなく、毎回1回インスタンスを取得しています。このラインは毎回ViewModelの単一インスタンスを見つけるためです。 ActivateItem(_screenList.FirstOrDefault(c => c.GetType() == message.VMtype));

しかし、私はViewModelを無効にする必要があります(私はそれをScreenクラスのOnDeactivateメソッドを使って行う必要があると思います)。しかし、私はいつもViewModelの新しいインスタンスを_screenListから得る方法を知らない。私の考えはある種のファクトリを作成することですが、MEFを使用してそれを実装する方法や、ビューが非アクティブになるたびにViewModelを処分する方法はわかりません。

SHORT VERSION:これは[Export(typeof(Screen))]属性でマークされたすべてのコンポーネントをインポートします

private IEnumerable<Screen> _screenList { get; set; } 

[ImportingConstructor] 
public MainViewModel(IEventAggregator eventAggregator, [ImportMany]IEnumerable<Screen> screenList) 
{ 
    _screenList = screenList; 
} 

:MEFでは -TLDR-

、私はこのような何かを持つことができます。ただし、これらのコンポーネントのそれぞれには、[Export(typeof(ViewModelX))]のような他の属性も付いています。基本的にScreenは、各ViewModelの派生元となる基本クラスです。私のアプリケーションで

、私はそうのような_screenListを使用しています: ActivateItem(_screenList.FirstOrDefault(c => c.GetType() == typeof(ViewModelX)));

をしかし、私の問題で、私は_screenListViewModelXたびの新しいインスタンスを返すようにしたいです。どうやってやるの?

答えて

0

最後に、問題の解決策を見つけました。 ExportFactoryを使用して問題を解決しました。

実装は次のとおりです。

private IEnumerable<ExportFactory<Screen>> _screenList { get; set; } 

[ImportingConstructor] 
public MainViewModel(IEventAggregator eventAggregator, [ImportMany] IEnumerable<ExportFactory<Screen>> screenList) 
{    
    _screenList = screenList; 
    _eventAggregator = eventAggregator;      
    _eventAggregator.Subscribe(this); 
    ShowMenu(); 
} 

public void Handle(ViewModelType message) 
{ 
    ActivateItem(_screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message.VMtype).CreateExport().Value); 
} 
関連する問題