WPF Window 使用 MVVM 而不是框架(甚至不是 MSFT)的导航
WPF Window Navigation using MVVM but not frameworks(not even MSFT)
只是为了不将其标记为重复项。我发现了很多类似的问题,但它们依赖于框架的使用(第 3 部分或基于 MSFT)。还有一些建议内置的页面导航功能,这不是我想要的。
现在回到最初的问题。
我正在开发一个采用 MVVM 模式的 WPF 应用程序,没有 Prism 或任何框架,只有 基本 MVVM 概念。我希望从 Window 1 (Login
) 导航到 Window 2 (MainWindow
),然后返回到 Window1 (Logout
) .我试图了解什么是实现这一目标的最佳方式。我不是在寻找解决方法,而是在寻找 概念方法 来处理这种情况以更好地理解 MVVM。
Window
MVVM 模式的导航有点棘手。该模式最适合 Page
导航或 SPA(单页应用程序)用户界面。
但是,这并不意味着没有框架就不能完成。
首先,重要的是要注意没有代码隐藏不是 MVVM 中的要点。它是关于将代码放在它所属的地方。因此,从 Button
的点击事件中打开 Window
是完全有效的,因为它是 查看相关代码 .
的一部分
private void Button_Clicked(object sender, RoutedEventArgs e)
{
MyView view = new MyView();
view.Show();
}
尽量不要陷入代码隐藏是错误代码的想法中,因为事实并非如此。
为了使您的视图模型与 window 打开逻辑 分开,最好将其封装在 服务中。让我们看一个非常简单的例子:
public interface IWindowService
{
void OpenView(object viewModel);
}
public class WindowService
{
public void OpenView(object viewModel)
{
//Use reflection to get the view based on the view model name.
//Open the view
//Set the DataContext to be the view model.
}
}
注意:我不打算写太多代码,这纯粹是从概念的角度来看。
这个服务很简单,有一个方法需要一个视图模型,然后根据这个找到关联的视图,打开它,然后设置DataContext
。真的很简单
此服务可以扩展以处理对话 等等。
为了使用此服务,我们需要将其注入到视图模型中,像这样应该可以做到:
public class MyViewModel
{
private IWindowService _WindowService;
public MyViewModel(IWindowService windowService)
{
_WindowService = windowService;
}
...
}
您可以利用 Dependency Injection
将服务注入视图模型,请参阅 here。这里需要注意的是,我使用的是 interface
,这使我能够抽象出 window 服务的实现,这当然是一件好事。
剩下的就是打开一个视图,这可以通过调用OpenView
方法来完成:
SomeOtherViewModel myOtherViewModel = new SomeOtherViewModel();
_WindowService.OpenView(myOtherViewModel);
差不多就这些了。
只是为了不将其标记为重复项。我发现了很多类似的问题,但它们依赖于框架的使用(第 3 部分或基于 MSFT)。还有一些建议内置的页面导航功能,这不是我想要的。
现在回到最初的问题。
我正在开发一个采用 MVVM 模式的 WPF 应用程序,没有 Prism 或任何框架,只有 基本 MVVM 概念。我希望从 Window 1 (Login
) 导航到 Window 2 (MainWindow
),然后返回到 Window1 (Logout
) .我试图了解什么是实现这一目标的最佳方式。我不是在寻找解决方法,而是在寻找 概念方法 来处理这种情况以更好地理解 MVVM。
Window
MVVM 模式的导航有点棘手。该模式最适合 Page
导航或 SPA(单页应用程序)用户界面。
但是,这并不意味着没有框架就不能完成。
首先,重要的是要注意没有代码隐藏不是 MVVM 中的要点。它是关于将代码放在它所属的地方。因此,从 Button
的点击事件中打开 Window
是完全有效的,因为它是 查看相关代码 .
private void Button_Clicked(object sender, RoutedEventArgs e)
{
MyView view = new MyView();
view.Show();
}
尽量不要陷入代码隐藏是错误代码的想法中,因为事实并非如此。
为了使您的视图模型与 window 打开逻辑 分开,最好将其封装在 服务中。让我们看一个非常简单的例子:
public interface IWindowService
{
void OpenView(object viewModel);
}
public class WindowService
{
public void OpenView(object viewModel)
{
//Use reflection to get the view based on the view model name.
//Open the view
//Set the DataContext to be the view model.
}
}
注意:我不打算写太多代码,这纯粹是从概念的角度来看。
这个服务很简单,有一个方法需要一个视图模型,然后根据这个找到关联的视图,打开它,然后设置DataContext
。真的很简单
此服务可以扩展以处理对话 等等。
为了使用此服务,我们需要将其注入到视图模型中,像这样应该可以做到:
public class MyViewModel
{
private IWindowService _WindowService;
public MyViewModel(IWindowService windowService)
{
_WindowService = windowService;
}
...
}
您可以利用 Dependency Injection
将服务注入视图模型,请参阅 here。这里需要注意的是,我使用的是 interface
,这使我能够抽象出 window 服务的实现,这当然是一件好事。
剩下的就是打开一个视图,这可以通过调用OpenView
方法来完成:
SomeOtherViewModel myOtherViewModel = new SomeOtherViewModel();
_WindowService.OpenView(myOtherViewModel);
差不多就这些了。