我期望在 WinForms 中的行为是这样的:
GeneralWindow gw = new GeneralWindow(); this.Hide(); // or close gw.Show();
MVVM 模式将View 与ViewModel 分开。所以它没有资格从ViewModel 创建新的View。 创建窗口实例并从视图模型显示窗口违反了 MVVM"。所以我建议您使用流行的技术,您可以使用 ContentControl 和 DataTemplate 更改 Views。
让我们深入了解这项技术:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModelA}">
<localControls:ViewAUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModelB}">
<localControls:ViewBUserControl/>
</DataTemplate>
<Window.Resources>
<ContentPresenter Content="{Binding CurrentView}"/>
</Window>
如果Window.DataContext 是ViewModelA 的实例,则将显示ViewA,而Window.DataContext 是ViewModelB 的实例,则将显示ViewB。
让我举个例子,可以看到应该把DataTemplates放在哪里:
<Window x:Class="SimpleMVVMExample.ApplicationView"
...The code omitted for the brevity...
Title="Simple MVVM Example with Navigation" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModelA}">
<localControls:ViewAUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModelB}">
<localControls:ViewBUserControl/>
</DataTemplate>
</Window.Resources>
<DockPanel>
<Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
<ItemsControl ItemsSource="{Binding ListOfViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding }"
Margin="2,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<ContentControl Content="{Binding CurrentDataTemplateViewModel}" />
</DockPanel>
</Window>
我见过和读过的最好的例子是 Rachel Lim 的。 See the example.
更新:
如果你想真正打开新窗口,那么你应该创建一个中间层,使ViewModel不依赖于创建新窗口的具体实现。
public class YourViewModel
{
private readonly IWindowFactory windowFactory;
private ICommand openNewWindow;
public YourViewModel(IWindowFactory _windowFactory)
{
windowFactory = windowFactory;
/**
* Would need to assign value to m_openNewWindow here, and
* associate the DoOpenWindow method
* to the execution of the command.
* */
openNewWindow = null;
}
public void DoOpenNewWindow()
{
windowFactory.CreateNewWindow();
}
public ICommand OpenNewWindow { get { return openNewWindow; } }
}
public interface IWindowFactory
{
void CreateNewWindow();
}
public class ProductionWindowFactory: IWindowFactory
{
#region Implementation of INewWindowFactory
public void CreateNewWindow()
{
NewWindow window = new NewWindow
{
DataContext = new NewWindowViewModel()
};
window.Show();
}
#endregion
}
如何关闭一个窗口?
There are a lot of approaches.。其中之一是:
Application.Current.MainWindow.Close()