【发布时间】:2019-11-14 02:32:50
【问题描述】:
我正在尝试创建一个 WPF 应用程序,该应用程序显示登录视图,并在成功登录后显示第一、第二和第三页(如向导)。包括登录视图的每个“页面”都有其各自的ViewModel。我有一个MainWindow.xaml,其中包含四个UserControls,其中一个在任何给定状态下都可见。
我在处理可见性编排方面遇到了麻烦。对我来说最有意义的是 MainWindowViewModel 负责跟踪哪个 UserControl 是当前可见的,但我似乎无法让代码正常工作。
为了简单起见,我将只显示MainWindow 和LoginView 的相关文件。
MainWindow.xaml
<Grid>
<local:LoginView Visibility="{Not sure what to bind to here}" />
<local:PageOne Visibility="{Not sure what to bind to here}" />
<local:PageTwo Visibility="{Not sure what to bind to here}" />
<local:PageThree Visibility="{Not sure what to bind to here}" />
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
MainWindowViewModel.cs
公共类 MainWindowViewModel : BaseViewModel { 公共 ICommand WindowClosingCommand { 获取; }
public MainWindowViewModel()
{
WindowClosingCommand = new WindowClosingCommand(this);
}
}
LoginView.xaml
<UserControl x:Class="MyProject.View.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyProject.View"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="1200">
<Grid>
<!-- UI Layout stuff here -->
</Grid>
</UserControl>
LoginView.xaml.cs
public partial class Login : UserControl
{
public Login()
{
InitializeComponent();
DataContext = new LoginViewModel();
}
}
LoginViewModel.cs
public class LoginViewModel : BaseViewModel
{
public ICommand ConnectCommand { get; }
public ICommand WindowClosingCommand { get; }
public LoginViewModel()
{
ConnectCommand = new ConnectCommand(this);
WindowClosingCommand = new WindowClosingCommand(this);
}
public string UserName { get; set; }
}
如您所见,我想避免在 .xaml.cs 文件后面的代码中添加大量逻辑,因为这是最佳实践,我有一个 ViewModel 用于其中的 .xaml 文件。现在,通常情况下,我会写如下内容:
public PageType CurrentPage;
public enum PageType
{
Login, PageOne, PageTwo, PageThree
}
public Visibility LoginVisibility
{
get { (CurrentPage == PageType.Login) ? Visibility.Visible : Visibility.Collapsed }
}
// Repeat for each of the other three pages
然后根据是否在每个页面上单击“下一步”或“返回”按钮,我将正确设置 CurrentPage 字段。
但是,如果我们再参考我的MainWindow.xaml,我就不能这样做了:
<local:LoginView Visibility="{Binding LoginVisibility}" />
因为LoginVisibility 不存在于LoginViewModel 中,而LoginViewModel 正是该用户控件的数据上下文。把那个字段放在那里感觉不对,因为所有ViewModels 都需要知道他们自己的可见性状态,并以某种方式将其传达给MainWindow。
基本上,我很困惑,不确定如何在我的应用程序的页面之间切换。任何帮助或指导将不胜感激。
【问题讨论】:
-
将
ContentControl与您的 VM 的数据模板一起使用。在 MainVM 上创建属性以存储当前 VM。一旦将内容控件绑定到当前视图模型,就不需要枚举。而且您也不需要处理可见性。 -
通常我会先推荐viewmodel。向导是我考虑在框架中使用页面的少数要求之一。您可以轻松地在框架内向前和向后导航。每个页面都保留它的视图状态。将对视图模型的引用放在 di 容器或资源或中介对象中,并使页面从中获取其数据上下文。如果您需要重置,请再次实例化页面并替换这些实例。
-
或者你可以先去viewmodel。你有用户控件。你有视图模型。您需要做的就是告诉它哪个 uc 用于哪个 vm,social.technet.microsoft.com/wiki/contents/articles/…