【问题标题】:Apply Ninject to work with "child viewmodels" in my C# WPF application应用 Ninject 在我的 C# WPF 应用程序中使用“子视图模型”
【发布时间】:2018-12-13 09:00:31
【问题描述】:

我在 WPF 应用程序上执行 Ninject - 依赖注入时遇到了一些问题。

我已经成功地为我的 MainView.xaml 和 MainViewModel.cs 进行了正确的依赖注入,我通过在我的 App.xaml.cs 中设置数据上下文来做到这一点。有了这个,我将我的 MainWindow 数据文本设置为内核从 ninject 检索到的视图模型。

这是我的 App.xaml.cs,我在 app.xaml 中将其设置为 Startup 而不是 StartupUri

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        var kernel = new StandardKernel(new CompositionModule());

        MainWindow mainWindow = new MainWindow();
        mainWindow.DataContext = kernel.Get<MainViewModel>();
        mainWindow.Show();
    }

到目前为止,它非常适合 MainViewModel,但我的问题是我的 MainViewModel 有多个子视图模型。

这是我的子视图模型的示例,我的 MainView.xaml 看起来像 - 从下面你可以看到我的 MainView.xaml 将主窗口分成两部分。主窗口的一部分显示view1 和viewmodel1,另一部分显示view2 和viewmodel2。两者都在同一个窗口中,我这样做只是为了更容易显示这些部分的作用。我的问题是,现在我正在绑定 Content = Viewmodel1,但是当我尝试将参数值放入构造函数时,我的应用程序不会执行构造函数代码。它只是跳过它。我的子视图模型属于部分类,它由 viewmodel1.cs 和 viewmodel.commands.cs 组成。 viewmodel.commands 部分仅包含 GUI 的命令。 ContentTemplate 是我的 xaml 资源中的数据模板 - app.xaml 中加载的资源字典文件。

<telerik:RadSplitContainer Orientation="Vertical" telerik:DockingPanel.InitialSize="750,200">
            <telerik:RadPaneGroup IsContentPreserved="False" telerik:ProportionalStackPanel.RelativeSize="200,300" >
                <telerik:RadPane Header="{Binding ViewModel1.Title, Mode=TwoWay}" 
                             CanUserClose="False" CanUserPin="False"
                             CanDockInDocumentHost="True">
                    <ContentControl ContentTemplate="{StaticResource View1Template}"  
                                Content="{Binding Viewmodel1}" />
                </telerik:RadPane>
            </telerik:RadPaneGroup>
            <telerik:RadPaneGroup IsContentPreserved="False" telerik:ProportionalStackPanel.RelativeSize="100,120">
                <telerik:RadPane Header="ViewModel2.Tile" 
                             CanUserClose="False" CanUserPin="False"
                             CanDockInDocumentHost="True">
                    <ContentControl ContentTemplate="{StaticResource View2Template}"  
                                Content="{Binding Viewmodel2}" />
                </telerik:RadPane>
            </telerik:RadPaneGroup>
         </telerik:RadSplitContainer>

这两个视图模型绑定到 MainView.xaml 中的内容。

public ViewModel1 ViewModel1 { get; set; } = new ViewModel1();
public ViewModel2 ViewModel2 { get; set; } = new ViewModel2();

如何使依赖注入也适用于我的子视图模型?似乎它不起作用的原因是因为每当我将接口作为构造函数参数时,构造函数都不会被执行。

感谢我能得到的任何帮助。它适用于 MainViewModel,但不适用于我的资源文件和其他视图模型。

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    我在您之前的问题上发布了此代码。当你设置

    public ViewModel1 ViewModel1 { get; set; } = new ViewModel1();
    

    那将忽略ninject。你只是在上新课。

    当我阅读您的问题时,我发布的示例代码似乎可以解决您遇到的问题。 当我要求 IVMOne 时,我告诉它它应该给我一个新的 VMOne 实例。 您似乎没有等效的代码。

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            var nj = new StandardKernel();
            nj.Bind<IVMOne>().To<VMOne>().InTransientScope();  //  <<<<<<<<<<<<<<<
    
            MainWindow mw = new MainWindow();
            mw.DataContext = nj.Get<MainWindowViewModel>();
            mw.Show();
        }
    

    看看我在哪里绑定 IVMOne? 这相当于您的 Viewmodel1 和 2。 您的代码中没有。

    当我获得将 IVMOne 作为 ctor 参数的 MainWindowViewModel 时。

    class MainWindowViewModel
    {
        public IVMOne VMOne { get; set; }
        public MainWindowViewModel(IVMOne vmOne)
        {
            VMOne = vmOne;
        }
    }
    

    因为我告诉它要给我什么,它传递了一个 VMOne 的实例。

    当我启动它时,我看到文本出现在我的文本块中。

        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBlock Text="{Binding VMOne.Hello}"/>
    </Grid>
    

    如果我在 mainwindowviewmodel ctor 上放置一个断点,我会在那里有一个 vmone 实例。

    您能否在获取 mainwindowviewmodel 之前尝试绑定您的视图模型之一?

    当您获取 mainwindowviewmodel 时,它将使用具有最多参数的 ctor。 在其中设置一个断点。 你有你的视图模型的实例吗?

    如果没有,则将不同的 sln 放在一起。 不是你现在拥有的。因为这会很复杂,并且可能有外部依赖项。 放入绝对最小的标记和代码,以演示您的问题,而无需任何外部依赖。

    这样有人可以轻松快速地重现您的问题。

    【讨论】:

    • 好的,如果我有 2 个构造函数作为部分类,我该怎么办?我有一个 viewmodel.cs 和 viewmodel.commands.cs。因为只有一个视图模型运行。似乎我必须选择将它放在视图模型或命令中。
    • 您选择他们所属的班级。部分类在编译时合并为一个,但您只能使用一个 ctor - 因为它们都是同一个类。
    • 是的,你是对的......那我应该将它保存在命令中还是 viewmodel.cs 中?
    • 不确定我是否关注。如果这是两个类,那么您可以将两者都作为 ctor 中的参数。另请注意,您并非绝对需要拥有接口并将它们绑定到所有类。除非您出于其他原因需要将它们切换出去。如果您获取 mainwindowviewmodel 并且它具有 VMOne 作为 ctor 参数,该参数将在您获取 mainwindowviewmodel 时提供。
    • 这个是为 ^ public MarketViewModel(IMarket) { _market = market; this.InitializeCommands(); AsyncContext.Run(GetMarketData); } 这个用于命令: public MarketViewModel() { this.InitializeCommands(); AsyncContext.Run(GetMarketData);只有这些构造函数在编译时运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多