[英]C# WPF Page Navigation Class
我正在尝试创建一个 class & 方法,该方法可用于任何 window 和页面以更改 MainWindow window 上显示的当前页面。
到目前为止,我得到了:
class MainWindowNavigation : MainWindow
{
public MainWindow mainWindow;
public void ChangePage(Page page)
{
mainWindow.Content = page;
}
}
主要的 window 本身:
public MainWindow()
{
InitializeComponent();
MainWindowNavigation mainWindow = new MainWindowNavigation();
mainWindow.ChangePage(new Pages.MainWindowPage());
}
不幸的是,这以 System.StackOverflowException 告终。
创建它的主要原因是我希望能够从当前显示在 mainWindow.Content 中的页面更改 mainWindow.Content。
我已经审查了 MVVM,但我认为它不值得将它用于像这样的小型应用程序,因为我想要它做的只是在打开时显示一个欢迎页面,然后在侧面会有几个按钮。 一旦按下 mainWindow.Content 正确更改为用户可以输入登录详细信息的页面,然后在登录页面上按下按钮,我想在成功验证输入的登录详细信息后将 mainWindow.Content 更改为不同的页面。
使用 MVVM 绝对没问题,因为它将简化您的需求的实现。 WPF 是为与 MVVM 模式一起使用而构建的,这意味着大量使用数据绑定和数据模板。
任务很简单。 为每个视图创建一个UserControl
(或DataTemplate
),例如WelcomePage
和LoginPage
及其对应的视图模型WelcomePageViewModel
和LoginPageViewModel
。
ContentControl
将显示页面。
主要技巧是,当使用隐式DataTemplate
(未定义x:Key
的模板资源)时,XAML 解析器将自动查找并应用正确的模板,其中DataType
与ContentControl
的当前内容类型匹配。 这使得导航非常简单,因为您只需从页面模型集合中 select 当前页面,并通过数据绑定到ContentControl
或ContentPresenter
的Content
属性设置此页面:
主窗口.xaml
<Window>
<Window.DataContext>
<MainViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type WelcomePageviewModel}">
<WelcomPage />
</DataTemplate>
<DataTemplate DataType="{x:Type LoginPageviewModel}">
<LoginPage />
</DataTemplate>
</Window.Resources>
<StackPanel>
<!-- Page navigation -->
<StackPanel Orientation="Horizontal">
<Button Content="Show Login Screen"
Command="{Binding SelectPageCommand}"
CommandParameter="{x:Static PageName.LoginPage}" />
<Button Content="Show Welcome Screen"
Command="{Binding SelectPageCommand}"
CommandParameter="{x:Static PageName.WelcomePage}" />
</StackPanel>
<!--
Host of SelectedPage.
Automatically displays the DataTemplate that matches the current data type
-->
<ContentControl Content="{Binding SelectedPage}" />
<StackPanel>
</Window>
创建页面控件。 这可以是Control
、 UserControl
、 Page
或只是一个DataTemplate
WelcomePage.xaml
<UserControl> <StackPanel> <TextBlock Text="{Binding PageTitle}" /> <TextBlock Text="{Binding Message}" /> </StackPanel> </UserControl>
登录页面.xaml
<UserControl> <StackPanel> <TextBlock Text="{Binding PageTitle}" /> <TextBox Text="{Binding UserName}" /> </StackPanel> </UserControl>
创建页面模型
网页文件
interface IPage: INotifyPropertyChanged { string PageTitel { get; set; } }
WelcomePageViewModel.cs
class WelcomePageViewModel: IPage { private string pageTitle; public string PageTitle { get => this.pageTitle; set { this.pageTitle = value; OnPropertyChanged(); } } private string message; public string Message { get => this.message; set { this.message = value; OnPropertyChanged(); } } public WelcomePageViewModel() { this.PageTitle = "Welcome"; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
LoginPageViewModel.cs
class LoginPageViewModel: IPage { private string pageTitle; public string PageTitle { get => this.pageTitle; set { this.pageTitle = value; OnPropertyChanged(); } } private string userName; public string UserName { get => this.userName; set { this.userName = value; OnPropertyChanged(); } } public LoginPageViewModel() { this.PageTitle = "Login"; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
创建页面标识符的枚举(以消除 XAML 和 C# 中的魔术字符串)
页面名称.cs
public enum PageName { Undefined = 0, WelcomePage, LoginPage }
创建将管理页面及其导航的MainViewModel
主视图模型.cs
RelayCommand
的实现可以在以下位置找到
Microsoft Docs:模式 - WPF 具有模型-视图-视图模型设计模式的应用程序 - 中继命令逻辑
class MainViewModel { public ICommand SelectPageCommand => new RelayCommand(SelectPage); public Dictionary<PageName, IPage> Pages { get; } private IPage selectedPage; public IPage SelectedPage { get => this.selectedPage; set { this.selectedPage = value; OnPropertyChanged(); } } public MainViewModel() { this.Pages = new Dictionary<PageName, IPage> { { PageName.WelcomePage, new WelcomePageViewModel() }, { PageName.LoginPage, new LoginPageViewModel() } }; this.SelectedPage = this.Pages.First().Value; } public void SelectPage(object param) { if (param is PageName pageName && this.Pages.TryGetValue(pageName, out IPage selectedPage)) { this.SelectedPage = selectedPage; } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
您可能希望使用简单地更改当前MainWindow
的Content
的方法将MainWindowNavigation
定义为 static class :
static class MainWindowNavigation
{
public static void ChangePage(Page page)
{
var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
mainWindow.Content = page;
}
}
然后,您可以从任何 class 调用该方法,而无需引用MainWindow
:
MainWindowNavigation.ChangePage(new Pages.MainWindowPage());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.