WPF Ninject 带 Datacontext 和带参数的构造函数
WPF Ninject with Datacontext and constructor with parameters
大家好,
我有一些使用 WPF 的经验,但我仍处于 MVVM 的开始阶段,现在我想将 DI 与 ninject 一起使用。当我使用表单时,我通常使用 ninject 通过创建一个带有绑定的内核来加载并在构造函数中插入参数,我发现这是不可能的,因为我必须使用 DataContext。
我在视图模型中有一个带有按钮和构造函数的主 window,为了使用 window 中的按钮,我需要从构造函数中的绑定传递参数,但如果我这样做所以我得到一个错误,因为数据上下文需要一个无参数的构造函数,我相信有一个明显的解决方案,我在 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;
}
不要像这样在 XAML 标记中实例化视图模型:
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
您只会在非常简单的情况下执行此操作,如果您想向 MainViewModel
注入一些依赖项,则无法使用此方法。相反,您可以以编程方式设置视图的 DataContext
属性,例如在实例化 MainWindow
:
的 OnStartup
方法中
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();
}
大家好, 我有一些使用 WPF 的经验,但我仍处于 MVVM 的开始阶段,现在我想将 DI 与 ninject 一起使用。当我使用表单时,我通常使用 ninject 通过创建一个带有绑定的内核来加载并在构造函数中插入参数,我发现这是不可能的,因为我必须使用 DataContext。 我在视图模型中有一个带有按钮和构造函数的主 window,为了使用 window 中的按钮,我需要从构造函数中的绑定传递参数,但如果我这样做所以我得到一个错误,因为数据上下文需要一个无参数的构造函数,我相信有一个明显的解决方案,我在 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;
}
不要像这样在 XAML 标记中实例化视图模型:
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
您只会在非常简单的情况下执行此操作,如果您想向 MainViewModel
注入一些依赖项,则无法使用此方法。相反,您可以以编程方式设置视图的 DataContext
属性,例如在实例化 MainWindow
:
OnStartup
方法中
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();
}