2015-04-28 3 views
0

Я стараюсь использовать Caliburn Micro в приложении WPF в сочетании с современным пользовательским интерфейсом. Я нахожу некоторые решения, которые используют контент загрузчик Caliburn однако он не работает вообще, вот код:Загрузитель контента Caliburn Micro и Modern UI

public class CaliburnContentLoader : DefaultContentLoader 
{ 
    protected override object LoadContent(Uri uri) 
    { 
     var content = base.LoadContent(uri); 
     if (content == null) 
     return content; 

     var vm = Caliburn.Micro.ViewModelLocator.LocateForView(content); 
     if (vm == null) 
     return content; 

     if (content is DependencyObject) 
     { 
     Caliburn.Micro.ViewModelBinder.Bind(vm, content as DependencyObject, null); 
     } 
     return content; 
    } 
} 

Для любого вида модели LocateForView метода каждый раз возвращает нуль. Я думаю, что проблема здесь в контейнере IoC, который по некоторым причинам пуст в моем CaliburnContentLoader.

Для большой картины здесь мой App XALM:

<Application x:Class="Astrea.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:Astrea"> 
    <Application.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary> 
        <local:Bootstrapper x:Key="bootstrapper" /> 
        <local:CaliburnContentLoader x:Key="CaliburnContentLoader" /> 
       </ResourceDictionary> 
       <ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" /> 
       <ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.Dark.xaml"/> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 

и MainWindow XAML

<mui:ModernWindow x:Class="Astrea.Views.MainWindowView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mui="http://firstfloorsoftware.com/ModernUI" 
     Title="mui" IsTitleVisible="True"   
     ContentLoader="{StaticResource CaliburnContentLoader}" 
     ContentSource="/Views/ChildView.xaml"> 

    <mui:ModernWindow.MenuLinkGroups> 
     <mui:LinkGroup DisplayName="nodes explorer"> 
      <mui:LinkGroup.Links> 
       <mui:Link DisplayName="home" Source="/Views/ChildView.xaml" /> 
      </mui:LinkGroup.Links> 
     </mui:LinkGroup> 

Может что-то не так в моем загрузчике? Вот код:

namespace Astrea 
{ 
    class Bootstrapper : BootstrapperBase 
    { 
     private CompositionContainer container; 

     public Bootstrapper() 
     { 
      Initialize(); 
     } 

     protected override void Configure() 
     { 
      // Add New ViewLocator Rule 
      ViewLocator.NameTransformer.AddRule(
      @"(?<nsbefore>([A-Za-z_]\w*\.)*)?(?<nsvm>ViewModels\.)(?<nsafter>([A-Za-z_]\w*\.)*)(?<basename>[A-Za-z_]\w*)(?<suffix>ViewModel$)", 
      @"${nsbefore}Views.${nsafter}${basename}View", 
      @"(([A-Za-z_]\w*\.)*)?ViewModels\.([A-Za-z_]\w*\.)*[A-Za-z_]\w*ViewModel$" 
      ); 

      container = new CompositionContainer(
        new AggregateCatalog(
        new AssemblyCatalog(typeof(IShellViewModel).Assembly), 
        AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>().FirstOrDefault() 
       ) 
      ); 

      var batch = new CompositionBatch(); 

      batch.AddExportedValue<IWindowManager>(new WindowManager()); 
      batch.AddExportedValue<IEventAggregator>(new EventAggregator()); 
      batch.AddExportedValue(container); 

      container.Compose(batch); 
     } 

     public T GetInstance<T>() 
     { 
      string contract = AttributedModelServices.GetContractName(typeof(T)); 

      var sexports = container.GetExportedValues<object>(contract); 
      if (sexports.Count() > 0) 
       return sexports.OfType<T>().First(); 

      throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract)); 
     } 

     protected override object GetInstance(Type serviceType, string key) 
     { 
      string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key; 

      var exports = container.GetExportedValues<object>(contract); 
      return exports.FirstOrDefault(); 
     } 

     protected override IEnumerable<object> GetAllInstances(Type serviceType) 
     { 
      //return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType)); 
      var ret = Enumerable.Empty<object>(); 

      string contract = AttributedModelServices.GetContractName(serviceType); 
      return container.GetExportedValues<object>(contract); 
     } 

     protected override void BuildUp(object instance) 
     { 
      container.SatisfyImportsOnce(instance); 
     } 

     protected override IEnumerable<Assembly> SelectAssemblies() 
     { 
      return new[] { 
      Assembly.GetExecutingAssembly() 
     }; 
     } 

     protected override void OnStartup(object sender, StartupEventArgs e) 
     { 
      DisplayRootViewFor<MainWindowViewModel>(); 
     } 
    } 
} 
+0

ContentLoader - объект MUI, с которым вы, вероятно, можете получить дополнительную помощь, но также и то, что я нашел, это http://mui.codeplex.com/discussions/436518 – mvermef

+0

Да, я это вижу. Я думаю, проблема здесь в контейнере IoC. [Здесь] (http://stackoverflow.com/questions/16421582/caliburn-micro-and-modernui-examples-tutorials) У Матиаса та же проблема. Я не знаю, является ли это контейнером или даже чем-то с пространством имен. Я пытаюсь даже написать что-то менее общее с жестко запрограммированным именем модели, но «IoC.getInstance» пуст, и я действительно не знаю, что я делаю неправильно. Я отлаживаю загрузчик, и действительно модели представления добавляются в контейнер IoC, но они исчезают в загрузчике контента. – Magnar

+0

Конечно, спасибо за предложения, я также добавлю этот тег. – Magnar

ответ

0

Я нахожу решение. Проблема здесь заключалась в контейнере MEF, который не работал бы с загрузчиком содержимого, или просто я не знаю, как заставить его работать.

Вместо контейнера MEF я попытался использовать простой контейнер IoC, поставляемый с Caliburn Micro, и он работает как вред.

Вот мой новый Загрузчик:

public class HelloBootstrapper : BootstrapperBase 
{ 
    private SimpleContainer container; 

    public HelloBootstrapper() 
    { 
     Initialize(); 
    } 

    protected override void Configure() 
    { 
     container = new SimpleContainer(); 
     container.Singleton<IWindowManager, WindowManager>(); 
     container.Singleton<IEventAggregator, EventAggregator>(); 
     container.PerRequest<ShellViewModel>(); 
     container.PerRequest<ModernWindowViewModel>(); 
    } 

    protected override IEnumerable<Assembly> SelectAssemblies() 
    { 
     return new[] { 
     Assembly.GetExecutingAssembly() 
    }; 
    } 

    protected override object GetInstance(Type serviceType, string key) 
    { 
     return container.GetInstance(serviceType, key); 
    } 

    protected override IEnumerable<object> GetAllInstances(Type serviceType) 
    { 
     return container.GetAllInstances(serviceType); 
    } 

    protected override void BuildUp(object instance) 
    { 
     container.BuildUp(instance); 
    } 

    protected override void OnStartup(object sender, StartupEventArgs e) 
    { 
     DisplayRootViewFor<ModernWindowViewModel>(); 
    } 
} 

Я не только знаю, как добавить все Просмотр модели в контейнер. Может быть, кто-то может помочь с этим и изменить этот раздел кода.

Смежные вопросы