在按钮上打开新窗口,单击WPF MVVM

whi*_*993 5 c# wpf xaml mvvm

我正在学习WPF MVVM,并希望在从主窗口单击按钮时打开一个新窗口。

我知道每个视图都必须有一个等效的ViewModel,而MVVM的基本原理之一是ViewModel必须不了解任何有关View的信息。

因此,请任何人为我提供一个简单干净的示例,该示例在创建两个具有以下功能的View和两个ViewModel时不违反任何MVVM原理:

通过单击主视图中的按钮来显示新视图。

Ste*_*pUp 5

您可以创建一个单独的服务来将视图作为对话框启动,以便可以在整个应用程序中以通用方式使用它。并将通过想要启动任何对话框的构造函数将此服务注入到 ViewModel 中。

public interface IDialogWindowService<T>
{
    void Show();
    void ShowDialog();
}

public class DialogWindowService<T> : IDialogWindowService<T> where T : Window
{
    public void Show()
    {
        container.Resolve<T>().Show();
    }

    public void ShowDialog()
    {
        container.Resolve<T>().ShowDialog();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在只需将此服务注入到相应的 ViewModel 中即可。

public class YourViewModel
{
    //commands
    public ICommand someCommand { get; set; }

    private IDialogWindowService<BookingView> _dialogService;
    public YourViewModel(IDialogWindowService<YourView > dialogService)
    {
        _dialogService = dialogService
        someCommand = new RelayCommand(someCommandDoJob, () => true);
    }

    public void someCommandDoJob(object obj)
    {
        //Since you want to launch this view as dialog you can set its datacontext in its own constructor.    
        _dialogService.ShowDialog();
    }
}
Run Code Online (Sandbox Code Playgroud)

或者

您可以使用DataTemplates来更改视图。它允许Views根据以下情况动态切换ViewModel

<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>
Run Code Online (Sandbox Code Playgroud)

如果 Window.DataContext 是 ViewModelA 的实例,则将显示 ViewA 并且

Window.DataContext是ViewModelB的实例,那么ViewB就会被显示。

我见过和读过的最好的例子是 Rachel Lim 制作的。请参阅示例。

  • 您正在引用 ViewModel 中的视图: private IDialogWindowService&lt;BookingView&gt; _dialogService; 这不是违反了MVVM吗? (3认同)
  • 在 YourViewModel 类中,“IDialogWindowService&lt;BookingView&gt;”类型引用“_dialogService”用于 BookingView 类型。假设您在另一个项目中有 BookingView,您是否必须添加对该项目的引用才能使用“IDialogWindowService&lt;BookingView&gt;”的引用?因此,如果您有两个项目,一个用于 ViewModels,一个用于 Views,您必须在 ViewModels 项目中引用 Views 项目,以便您可以在 YourViewModel 中使用 BookingView。如果我误解了什么,请纠正我。我只是想澄清一些事情。 (2认同)

Mik*_*son 2

根据您的使用情况,从视图的代码隐藏中打开视图没有任何问题。毕竟还是查看代码。

MyView view = new MyView();
view.Show();
Run Code Online (Sandbox Code Playgroud)

ViewModel否则,如果您需要从或 使用 a打开窗口ICommand,那么您可以查看我在GitHub上编写的“在 MVVM 中打开窗口和对话框”库。这将演示如何使用 MVVM 设计模式通过单击按钮来打开。Window