[英]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.