繁体   English   中英

C# WPF 页面导航 Class

[英]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 ),例如WelcomePageLoginPage及其对应的视图模型WelcomePageViewModelLoginPageViewModel

ContentControl将显示页面。
主要技巧是,当使用隐式DataTemplate (未定义x:Key的模板资源)时,XAML 解析器将自动查找并应用正确的模板,其中DataTypeContentControl的当前内容类型匹配。 这使得导航非常简单,因为您只需从页面模型集合中 select 当前页面,并通过数据绑定到ContentControlContentPresenterContent属性设置此页面:

用法

主窗口.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>

执行

  1. 创建页面控件。 这可以是ControlUserControlPage或只是一个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>
  2. 创建页面模型

    网页文件

    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)); } }
  3. 创建页面标识符的枚举(以消除 XAML 和 C# 中的魔术字符串)

    页面名称.cs

     public enum PageName { Undefined = 0, WelcomePage, LoginPage }
  4. 创建将管理页面及其导航的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)); } }

您可能希望使用简单地更改当前MainWindowContent的方法将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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM