(TLDR 버전은 아래입니다.) 프레임 워크로 IoC 및 Caliburn Micro로 MEF를 사용하여 WPF 응용 프로그램을 설계하고 있습니다.Caliburn Micro의 스크린 컨덕터와 함께 MEF 사용
다음는 윈도우의 뷰 모델입니다 : 응용 프로그램의 메인 화면은 다음과 같이이다
[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)));
}
그러나 문제는 f입니다. 이 라인은 MenuViewModel
에있는 버튼을 클릭 할 때 새 VM을 얻는 대신,이 라인이 매번 ViewModel의 단일 인스턴스를 찾기 때문에 반복적으로 단일 인스턴스를 얻게됩니다. ActivateItem(_screenList.FirstOrDefault(c => c.GetType() == message.VMtype));
하지만 뷰가 비활성화 될 때마다 ViewModel을 처리해야합니다 (Screen 클래스의 OnDeactivate 메서드를 사용하여 뷰를 비활성화해야합니다). 그러나 매번 _screenList
에서 ViewModel의 새로운 인스턴스를 얻는 방법을 모르겠습니다. 내 생각은 어떤 종류의 팩토리를 만드는 것이지만 MEF를 사용하여이를 구현하는 방법과 뷰가 비활성화 될 때마다 ViewModel을 처리하는 방법을 알지 못합니다.
SHORT VERSION :이이 [Export(typeof(Screen))]
특성으로 표시된 모든 구성 요소를 가져옵니다
private IEnumerable<Screen> _screenList { get; set; }
[ImportingConstructor]
public MainViewModel(IEventAggregator eventAggregator, [ImportMany]IEnumerable<Screen> screenList)
{
_screenList = screenList;
}
: -TLDR-
MEF에서, 나는 이런 식으로 뭔가를 할 수 있습니다. 그러나 각 구성 요소에는 [Export(typeof(ViewModelX))]
과 같은 다른 속성이 표시됩니다. 기본적으로 Screen
은 각 ViewModel을 파생시키는 기본 클래스입니다. 내 응용 프로그램에서
, 정말 같은 _screenList
을 사용하고 있습니다 : ActivateItem(_screenList.FirstOrDefault(c => c.GetType() == typeof(ViewModelX)));
그러나, 내 문제에, 내가 원하는 _screenList
을 ViewModelX
때마다 새로운 인스턴스를 반환 할 수 있습니다. 어떻게해야합니까?