Использование Ninject в качестве контейнера DI с Calburn.Micro и MVVM в WPF - PullRequest
1 голос
/ 27 мая 2020

Все У меня есть некоторый опыт работы с Caliburn.Micro с использованием System.ComponentModel.Composition в качестве контейнера Io C. На этот раз я хочу повеселиться и использовать Niject. Чтобы настроить загрузчик Calburn.Micro, у меня есть следующий класс

public class Bootstrapper : BootstrapperBase
{
    private IKernel _kernel;

    public Bootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        _kernel = new StandardKernel();
        _kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
        _kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();
        _kernel.Bind<IMainWindowViewModel>().To<MainWindowViewModel>().InSingletonScope();
    }

    protected override object GetInstance(Type service, string key)
    {
        return _kernel.Get(service);
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return _kernel.GetAll(service);
    }

    protected override void OnStartup(object sender, StartupEventArgs suea)
    {
        base.OnStartup(sender, suea);
        DisplayRootViewFor<IMainWindowViewModel>();
    }

    protected override void OnExit(object sender, EventArgs e)
    {
        _kernel.Dispose();
        base.OnExit(sender, e);
    }
}

Кажется, это нормально, но когда строка

DisplayRootViewFor<IMainWindowViewModel>();

нажата, кажется, что запускается просмотр IMainWindowView в порядке, но

public partial class MainWindowView : Window
{
    public MainWindowView()
    {
        InitializeComponent();
    }
}

public interface IMainWindowViewModel { }

и MainWindowViewModel как

public class MainWindowViewModel : Conductor<IMainWindowViewModel>, IMainWindowViewModel { }

с XAML IMainWindowView как

<Window x:Class="Mole.Replay.Framework.MainWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:ViewModels="clr-namespace:Mole.Replay.Framework"
        xmlns:local="clr-namespace:Mole.Replay.Framework"
        mc:Ignorable="d" 
        d:DesignHeight="450" d:DesignWidth="800">
    <Window.DataContext>
        <ViewModels:MainWindowView/>
    </Window.DataContext>
    <Grid>

    </Grid>
</Window>

ctor вызывается и снова, и приводит к исключению StackOverflow, нет явной причины для этого чего-то. Этот тип привязан к одноэлементной области. Почему это происходит? Я что-то упускаю?

1 Ответ

2 голосов
/ 27 мая 2020
<Window.DataContext>
    <ViewModels:MainWindowView/>
</Window.DataContext>

нет смысла устанавливать DataContext из MainWindowView в другой экземпляр MainWindowView, который также будет пытаться установить DataContext et c, пока вы не получите исключение StackOverflow.

это должно быть модель просмотра в DataContext. Я не знаю, создает ли caliburn.micro модели представления для представления на основе соглашений, но по крайней мере удалите текущее назначение <Window.DataContext>.

мне не ясно, почему пространство имен представления имеет псевдоним ViewModels. Если реальная модель представления находится в том же пространстве имен и не разрешается автоматически, назначьте модель представления

<Window.DataContext>
    <ViewModels:MainWindowViewModel/>
</Window.DataContext>

Контейнер DI действительно должен предоставлять аргументы конструктора. Используйте их для назначения DataContext:

public MainWindowView(IMainWindowViewModel vm)
{
    InitializeComponent();
    DataContext = vm;
}
...