Я пытаюсь построить этот проект, используя Caliburn в первый раз (а также структуру MEF, которую я не совсем понял).
Мне нужно использовать и Проводник, и EventAggregator. Проводник, потому что у меня есть AppViewModel, который «отображает» 3 кнопки, которые перемещают пользователя в 3 разных представления (UserControls внутри AppView).
И мне нужен EventAggregator, потому что в одном из этих трех представлений есть кнопка внутри, которая должна загружать 4-е представление (я думаю, это должно быть окно, а не пользовательский элемент управления, потому что он должен быть полноэкранным). Итак, я подумал, что когда пользователь нажимает эту кнопку внутри 3-го представления (UserControl внутри AppView), сообщение может быть отправлено поверх прослушивателя (это должна быть AppViewModel), а это должно быть ActivateItem (4th vm).
Не знаю почему, но даже по примерам проектов Caliburn мое сообщение не доходит до AppViewModel.
Это мой загрузчик:
public class AppBootstrapper : Bootstrapper<AppViewModel>
{
private CompositionContainer container;
protected override void Configure()
{
container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x =>
new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));
CompositionBatch batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(container);
container.Compose(batch);
}
protected override object GetInstance(Type serviceType, string key)
{
string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
var exports = container.GetExportedValues<object>(contract);
if (exports.Any())
return exports.First();
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
protected override void BuildUp(object instance)
{
container.SatisfyImportsOnce(instance);
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<AppViewModel>();
}
}
Это AppViewModel:
[Export (typeof(AppViewModel))]
public class AppViewModel : Conductor<object>, IHandle<ChangeViewEvent>
{
[ImportingConstructor]
public AppViewModel(IEventAggregator events)
{
events.Subscribe(this);
ActivateItem(new MainViewModel());
}
public void GoToPatientsManager()
{
ActivateItem(new PatientsManagerViewModel(new WindowManager(), new EventAggregator()));
}
public void GoToTestManager()
{
ActivateItem(new TestManagerViewModel(new WindowManager()));
}
public void GoToResultsManager()
{
ActivateItem(new MainViewModel());
}
public void Handle(ChangeViewEvent message)
{
switch (message.ViewName)
{
case "TestManager" :
GoToTestManager();
break;
}
}
}
А это модель представления, которая должна запускать запрос на загрузку 4-й вм
[Export(typeof(PatientsManagerViewModel))]
public class PatientsManagerViewModel : Screen
{
private readonly IWindowManager _windowManager;
private readonly IEventAggregator eventAggregator;
[ImportingConstructor]
public PatientsManagerViewModel(IWindowManager windowManager, IEventAggregator eventAggregator)
{
_windowManager = windowManager;
this.eventAggregator = eventAggregator;
}
#region Methods
public void ShowFakeMessage()
{
dynamic settings = new ExpandoObject();
settings.Placement = PlacementMode.Center;
settings.PlacementTarget = GetView(null);
var res = _windowManager.ShowDialog(new DeletePersonViewModel(), null, settings);
if (res)
{
// The result of the dialog men. In this true case we'll use Linq to delete the entry from the database
// using the dbContext
}
}
public void GoToTestManager()
{
eventAggregator.Publish(new ChangeViewEvent("TestManager"));
}
#endregion
}
Он не достигает метода Handle модели AppViewModel.
Это что-то не так с экземплярами моделей представления? Я не могу двигаться дальше отсюда...
РЕДАКТИРОВАТЬ
Может быть, проблема в том, что я передаю новый объект EventAggregator каждый раз, когда активирую новую модель PatientManagerViewModel? Какие-нибудь советы?