WPF Ninject с Datacontext и конструктор с параметрами - PullRequest
0 голосов
/ 02 июля 2018

Добрый день всем, У меня есть некоторый опыт работы с WPF, но я все еще начинаю с MVVM, и теперь я хотел бы использовать DI с ninject. Когда я работал с формами, я обычно использовал ninject, создавая ядро ​​с привязками для загрузки и вставляя параметры в конструктор, я вижу, что это невозможно сейчас, когда мне нужно использовать DataContext. У меня есть главное окно с кнопками и конструктор в View Models, чтобы использовать кнопки в окне I, что мне нужно передать параметры из привязки в конструкторе, но если я это сделаю, я получаю ошибку, потому что datacontext нужен конструктор без параметров, я думаю, что есть очевидное решение, которое я не смог найти конкретное на Ninject (сайты), и в Интернете единственные обходные пути используют какой-то сложный шаблон фабрики, который кажется излишним, кто-нибудь знает, как решить проблему?

MainWindow.xaml

<Window x:Class="StretchApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:StretchApp"
        xmlns:vm="clr-namespace:StretchApp.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="800" Width="800" Background="LightGray"
    DataContextChanged="MainWindow_DataContextChanged">
    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>

MainWindow.xaml.cs

namespace StretchApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IHavePassword
    {
        private IKernel container;

        public MainWindow()
        {
            InitializeComponent();
            DataContextChanged += new DependencyPropertyChangedEventHandler(MainWindow_DataContextChanged);
        }
        void MainWindow_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var dc = DataContext as IClosableViewModel;
            dc.CloseWindowEvent += new EventHandler(dc_CloseWindowEvent);
        }
        void dc_CloseWindowEvent(object sender, EventArgs e)
        {
            this.Close();
        }
        private void ConfigureContainer()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
        }

    }
}

App.xaml

<Application x:Class="StretchApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:StretchApp"
             xmlns:local1="clr-namespace:StretchApp.ViewModels">

    <Application.Resources>
    </Application.Resources>
</Application>

App.xaml.xs

sing Ninject;
using StretchApp.Helper;
using StretchApp.Helper.Interfaces;
using System.Windows;

namespace StretchApp
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        private IKernel container;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            var container = new StandardKernel();

            // Register types
            container.Bind<IEncrypterHelper>().To<EncrypterHelper>();
            container.Bind<Window>().To<MainWindow>();

            // Show the main window.
            MainWindow mw = new MainWindow();
            mw.Show();

        }
        private void ComposeObjects()
        {
            Current.MainWindow = this.container.Get<MainWindow>();
        }

        private void ConfigureContainer()
        {
            this.container = new StandardKernel();
            container.Bind<IEncrypterHelper>().To<EncrypterHelper>();

        }
    }
}

MainViewModel.cs

        public MainViewModel(IEncrypterHelper encrypterHelper)
        {
           _encrypterHelper = encrypterHelper;

        }

1 Ответ

0 голосов
/ 02 июля 2018

Не создавайте экземпляр модели представления в разметке XAML следующим образом:

<Window.DataContext>
    <vm:MainViewModel/>
</Window.DataContext>

Это можно сделать только в очень простых сценариях, и этот подход невозможно использовать, если вы хотите внедрить MainViewModel с некоторыми зависимостями. Вместо этого вы можете установить свойство DataContext представления программно, например, в вашем методе OnStartup, где вы создаете экземпляр MainWindow:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    var container = new StandardKernel();

    // Register types
    container.Bind<IEncrypterHelper>().To<EncrypterHelper>();
    container.Bind<Window>().To<MainWindow>();

    // Show the main window.
    MainWindow mw = new MainWindow();
    mw.DataContext = container.Get<MainWindowViewModel>();
    mw.Show();
}
...