在 MVVM 和松散耦合之后从 MainWindow 打开第二个 Window
Opening a second Window from MainWindow following MVVM and loose coupling
起初:这个应用程序和问题是为了学习目的
我正在使用一个新应用程序并面临这样的问题,即当用户单击 MainView 中的按钮时我想打开一个 Window。在过去,我会设计一个命令来创建新的 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
中创建第二个 Window 的实例
<Window.Resources>
<local:SecondWindow x:Key="sw"/>
</Window.Resources>
并将其作为命令参数传递给我的命令
CommandParameter="{StaticResource sw}"/>
new RelayCommand((x)=> ((Window)x).Show());
此解决方案有效但有一个很大的缺点 - 第二个 window get 是在应用程序启动后立即创建的 - ViewModel 也是如此,它启动一些繁重的进程(数据库连接等)
我听说过一些关于 IoC 原则的事情,但我真的不知道如何将它用于 wpf 应用程序。
您的思路是正确的....您基本上必须在应用程序启动时创建一个 ViewModel 列表,然后您可以在用户按下按钮时在它们之间切换并将 ViewModel 的名称传递为您的命令处理程序的 CommandParameter....
您可能会在 Rachel Lim 的博客link 中找到这个
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
此外,我不打算 post 此处的任何代码,因为它太复杂了。所以这里是我能想到的最简单示例的下载
http://www.mediafire.com/download/3bubiq7s6xw7i73/Navigation1.rar
下载并解压缩它(使用 win RAR)您将需要单步执行代码,弄清楚它在做什么以及它是如何做的然后修改它以满足您的需要...或者修改您的需要以适合代码.....
该示例是 Rachel Lim 示例的修改版。它只包含视图和视图模型,没有模型或数据。它演示了两个不同视图之间的切换。
更新 1
具体参考演示代码....您的 VM 被添加到 VM 的静态集合中(请参阅 AddViewModel 函数),当您单击一个按钮例如,通过调用 'SelectViewCommand',它又将 Current_ViewModel 设置为选定的 ViewModel... 然后更新相应的 ContentControl 以显示当前选定的视图...
我知道这很混乱,很难解释
当您按下按钮 'change Views' 时,您实际上是在更改您的 ContentControl 绑定到的 属性 的值,因此您必须在class 你的 ContentControl 也被绑定了...
在演示中你会看到 'LogOn_View' 我调用
Command="{Binding DataContext.SelectViewCommand, ElementName=Base_V}"CommandParameter="Main_ViewModel"
这里我调用的是Base_ViewModel中的SelectViewCommand(x:Name="Base_V" in Base_View XAML),那是因为我想改变那个View显示在 Base_View 的 'ContentControl'
在Main_View我叫
Command="{Binding SelectViewCommand}" CommandParameter="MainV1_ViewModel"
这里我调用了Main_ViewModel中的SelectViewCommand,那是因为我想改变MainView中显示的View 'ContentControl'.....
我通常创建一个 WindowService class 用于在 MVVM 中管理 window changes/dialogs。在 ViewModel 中使用 "View" 代码(即 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 容器的引用传递给 window 服务并从中创建 window 实例,而不是使用 Activator.CreateInstance(我个人更喜欢 DI 方法)
起初:这个应用程序和问题是为了学习目的
我正在使用一个新应用程序并面临这样的问题,即当用户单击 MainView 中的按钮时我想打开一个 Window。在过去,我会设计一个命令来创建新的 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
中创建第二个 Window 的实例<Window.Resources>
<local:SecondWindow x:Key="sw"/>
</Window.Resources>
并将其作为命令参数传递给我的命令
CommandParameter="{StaticResource sw}"/>
new RelayCommand((x)=> ((Window)x).Show());
此解决方案有效但有一个很大的缺点 - 第二个 window get 是在应用程序启动后立即创建的 - ViewModel 也是如此,它启动一些繁重的进程(数据库连接等)
我听说过一些关于 IoC 原则的事情,但我真的不知道如何将它用于 wpf 应用程序。
您的思路是正确的....您基本上必须在应用程序启动时创建一个 ViewModel 列表,然后您可以在用户按下按钮时在它们之间切换并将 ViewModel 的名称传递为您的命令处理程序的 CommandParameter....
您可能会在 Rachel Lim 的博客link 中找到这个
https://rachel53461.wordpress.com/2011/12/18/navigation-with-mvvm-2/
此外,我不打算 post 此处的任何代码,因为它太复杂了。所以这里是我能想到的最简单示例的下载
http://www.mediafire.com/download/3bubiq7s6xw7i73/Navigation1.rar
下载并解压缩它(使用 win RAR)您将需要单步执行代码,弄清楚它在做什么以及它是如何做的然后修改它以满足您的需要...或者修改您的需要以适合代码.....
该示例是 Rachel Lim 示例的修改版。它只包含视图和视图模型,没有模型或数据。它演示了两个不同视图之间的切换。
更新 1
具体参考演示代码....您的 VM 被添加到 VM 的静态集合中(请参阅 AddViewModel 函数),当您单击一个按钮例如,通过调用 'SelectViewCommand',它又将 Current_ViewModel 设置为选定的 ViewModel... 然后更新相应的 ContentControl 以显示当前选定的视图...
我知道这很混乱,很难解释
当您按下按钮 'change Views' 时,您实际上是在更改您的 ContentControl 绑定到的 属性 的值,因此您必须在class 你的 ContentControl 也被绑定了...
在演示中你会看到 'LogOn_View' 我调用
Command="{Binding DataContext.SelectViewCommand, ElementName=Base_V}"CommandParameter="Main_ViewModel"
这里我调用的是Base_ViewModel中的SelectViewCommand(x:Name="Base_V" in Base_View XAML),那是因为我想改变那个View显示在 Base_View 的 'ContentControl'
在Main_View我叫
Command="{Binding SelectViewCommand}" CommandParameter="MainV1_ViewModel"
这里我调用了Main_ViewModel中的SelectViewCommand,那是因为我想改变MainView中显示的View 'ContentControl'.....
我通常创建一个 WindowService class 用于在 MVVM 中管理 window changes/dialogs。在 ViewModel 中使用 "View" 代码(即 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 容器的引用传递给 window 服务并从中创建 window 实例,而不是使用 Activator.CreateInstance(我个人更喜欢 DI 方法)