在MVVM和松散耦合之后从MainWindow打开第二个窗口

时间:2016-04-07 13:19:13

标签: c# wpf xaml mvvm inversion-of-control

首先:此应用和问题仅供学习之用

我正在使用一个新的应用程序,当用户点击MainView中的Button时,我想要打开一个Window。在过去,我设计了一个只创建新窗口并显示它的命令

new RelayCommand((x)=>new SecondWindow().Show());

现在有了这个新项目,我试图将所有类完全分离。为实现这一目标,我的应用程序包含4个程序集(BL,COM,DAL和UI)。 与每个WPF应用程序一样,应用程序以MainWindow.xaml开头。 MainWindow.cs将创建它的MainWindowViewModel实例:

public ViewModel VM {get; private set;}
public class MainWindow(){
    VM = new ViewModel();
    InitializeComponent();
}

(已经违反松散耦合)(关于如何改善它的任何提示?)

我的最后一次尝试是在主窗口中创建第二个窗口的实例

<Window.Resources>
    <local:SecondWindow x:Key="sw"/>
</Window.Resources>

并将其作为CommandParameter传递给我的命令

CommandParameter="{StaticResource sw}"/>

new RelayCommand((x)=> ((Window)x).Show());

这个解决方案有效,但有一个很大的缺点 - 第二个窗口是在应用程序启动后立即创建的 - 它也是ViewModel,它启动了一些繁重的进程(DB Connections等)。

我听说过IoC原则,但我真的不知道如何在wpf应用程序中使用它。

2 个答案:

答案 0 :(得分:1)

你正在考虑正确的思路....当你的应用程序启动时,你基本上必须创建一个ViewModel列表,然后当用户按下按钮并将ViewModel的名称作为CommandParameter传递时,你可以在它们之间切换到你的命令处理程序....

您可能会发现此链接指向Rachel Lim的博客

https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/

另外,我不会在这里发布任何代码,因为它太复杂了。所以这里是一个下载到我能提出的最简单的例子

http://www.mediafire.com/download/3bubiq7s6xw7i73/Navigation1.rar

下载并取消RAR(使用win RAR)您需要逐步完成代码,弄清楚它的作用以及它如何进行修改然后根据您的需要进行修改......或修改您的需求以适应代码.....

该示例是对Rachel Lim示例的修改。它只包含Views和ViewModels,没有模型或数据。它演示了两种不同视图之间的切换。

更新1

具体参考演示代码....您的VM被添加到静态虚拟机集合(请参阅AddViewModel函数),例如,当您单击按钮时,每个视图(DataTemplate将View与ViewModel关联)都被选中,通过调用&#39; SelectViewCommand&#39;然后将Current_ViewModel设置为选定的ViewModel ...然后更新相应的ContentControl以显示当前选择的View ...

我知道这很困惑,也很难解释

按下按钮以更改视图&#39;您实际上是在更改ContentControl绑定的属性的值,因此您必须在ContentControl绑定的类的SAME实例中调用正确的SelectViewCommand ...

在演示中,您会在“LogOn_View”中看到这一点。我打电话给

 Command="{Binding DataContext.SelectViewCommand, ElementName=Base_V}"CommandParameter="Main_ViewModel"

这里我在Base_ViewModel中调用SelectViewCommand(x:Name =&#34; Base_V&#34;在Base_View XAML中),这是因为我想要更改Base_View中显示的视图&#39 ; s&#39; ContentControl&#39;

在Main_View中我调用

 Command="{Binding SelectViewCommand}" CommandParameter="MainV1_ViewModel"

这里我在Main_ViewModel中调用SelectViewCommand,因为我想更改MainView&#39; ContentControl&#39; ....中显示的视图。

答案 1 :(得分:0)

我通常创建一个WindowService类来管理MVVM中的窗口更改/对话框。拥有&#34;查看&#34; ViewModel中的代码(即Window.Show())违背了MVVM原则。例如:

public class WindowService : IWindowService
{
    public void ShowDialog<T>(ViewModelBase viewModel) where T : IApplicationDialog
    {
        IApplicationDialog dialog = (IApplicationDialog)Activator.CreateInstance(typeof(T));

        dialog.Show();
    }
}

然后来自ViewModel的调用看起来像:

windowService.ShowDialog<SecondWindow>(new SecondWindowViewModel());

如果您正在使用DI,您可以将对IoC容器的引用传递给窗口服务并从中创建窗口实例而不是使用Activator.CreateInstance(我更喜欢DI方法)