2

我正在构建一个基于 WPF 的销售点系统来练习使用 MVVM。我没有使用任何 MVVM 框架,而是使用了RelayCommandJosh Smith http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030文章中的类

我以前写过一个,没有应用 MVVM 模式(仍然使用 WPF)。
对于数据库访问,我使用了实体框架。它看起来像这样:

我的问题是,如何使用 MVVM 实现这一点?Login首先,我已经使用 MVVM编写了窗口,我的直接问题是,

  1. 如何关闭Login窗口(处理它)并打开MainWindow
  2. 在非 MVVM 版本中,MainWindow仅包含屏幕截图的顶部,即按钮行。
  3. 我是否应该将“按钮栏”进一步拆分为它自己的Viewand ViewModel,使用MainWindowonly 作为将所有内容放在一起的地方?
  4. 如果是这样,当单击按钮时,我如何编写代码,“按钮栏”ViewModel会告诉MainWindow'sViewModel将相应View的 s(我System.Windows.Controls.Page在非 MVVM 版本中使用)加载到Frame?在非 MVVM 版本中,我使用的代码相当简单:

    private void btnCheckout_Click(object sender, RoutedEventArgs e) {
        mainFrame.Navigated += frame_Navigated;
        var pgCheckout = new pgCheckout();
        mainFrame.Navigate(pgCheckout); //The frame
    }
    
  5. 如果没有,我如何将另一个加载PageFrame?

4

2 回答 2

1

解决这些问题的一种方法是创建一个负责加载和卸载视图的对象。

在应用程序开始时,会为此对象创建一个实例,该对象将显示一个窗口(将显示所有视图),创建一个 ViewModel 和一个 View 的实例,将 View 的 DataContext 设置为 ViewModel 并传递查看窗口以便显示(例如,设置为 Grid 的子项)

关闭一个视图和/或打开另一个视图:当当前视图模型的命令被执行时,一条消息可以被发送到同一个对象。该对象可以向 Window 发出信号以关闭当前视图,并且可以以与打开第一个视图相同的方式打开一个新视图。该命令甚至可以传递一个指示必须加载的 ViewModel 的参数。

要发送消息,我推荐使用弱事件传递消息的 MessageBroker。如果您不使用弱事件,则应用程序有占用内存的风险,因为事件处理程序会阻止垃圾收集清理。请参阅MVVM Light 以获得这样的 Messenger

关于你的问题:

  1. 请按照上述步骤操作。

  2. 3. 是否拆分 ViewModels 和 Views 是一个重用和分解的问题,就像在任何其他应用程序中一样。

  3. 5. 不要对点击事件进行编码。执行传递所需视图、ViewModel 以及可能承载视图的容器(ContentControl?)的命令。

于 2013-05-10T08:52:51.020 回答
1

如果您不使用任何现有框架,则必须自己创建一个。IMO 你可以从中受益,因为你可以控制一切,但你也必须重新发明很多东西。我可以描述我们是如何做到的,无论是对还是错,让这里的投票决定:)

首先你不想用任何与 UI 相关的对象污染 ViewModel 代码。但是,ViewModel 是关于视图逻辑的,您需要以某种方式控制演示(导航、用户消息......)。所以你可以在你的视图模型中引入某种视图服务来控制视图相关的逻辑,但不依赖于 UI 框架中的任何东西。让我们这样说:

public interface IViewService
{
   //show message dialog with message text
   void ShowMessageDialog(string message);
   //show Yes/No message dialog with message text. Retrun true if answer is Yes 
   bool AskQuestion(string message);
   //Navigate to some other viewmodel
   void NavigateTo(ViewModel someOtherViewModel);      
}

并且您必须使用 WPF 相关逻辑创建此类服务的具体实现。如何实现这些方法取决于您和您使用的 UI 框架(在本例中为 WPF)。

在您的视图模型中,您需要以某种方式获取实现IViewService. 您可以使用依赖注入来注入它,使用服务定位器获取实例,甚至可以使用一些硬编码的静态单例实例。(IMO 依赖注入是可行的方法,但也使事情进一步复杂化,您需要引入 DI 容器并使用 DI 容器创建所有视图模型实例)。

在您的命令中,您可以调用服务的方法。

假设您的 LoginViewModel 的 LoginCommand (RelayCommand登录按钮绑定到)

private void ExecuteLoginCommand(object parameter)
{
      bool loginOk = Login(.....);
      if(loginOk)
         viewService.NavigateTo(new MainWindowViewModel);
      else
         viewService.ShowMessage("Login failed");
}

最重要的是,ViewModel 控制着展示相关的逻辑,但对背后的 UI 框架一无所知。所有“WPF”代码都在实现 IViewService 的类中。在您的视图模型中,您“编程到接口”因此您不会与 WPF 逻辑紧密耦合,您的视图模型是“可测试的”,您甚至可以在其他一些 UI 平台上重用相同的视图模型代码。

于 2013-05-10T09:30:41.330 回答