(TLDRバージョンは以下です。)私はMEFをIoC、Caliburn MicroをフレームワークとしてWPFアプリケーションを設計しています。アプリケーションのメインウィンドウは次のようである:ここではCaliburn MicroのスクリーンコンダクターでMEFを使用する
の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)));
をしかし、私の問題で、私は_screenList
がViewModelX
たびの新しいインスタンスを返すようにしたいです。どうやってやるの?