C#WPF页面导航类 [英] C# WPF Page Navigation Class

查看:156
本文介绍了C#WPF页面导航类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个类&可以在任何窗口和页面上使用的方法来更改MainWindow窗口上显示的当前页面.

I'm attempting to create a class & method which could be used on any window and page to change the current page displayed on the MainWindow window.

到目前为止,我得到了:

So far I got:

class MainWindowNavigation : MainWindow
{
    public MainWindow mainWindow;

   public void ChangePage(Page page)
    {
        mainWindow.Content = page;
    }
}

主窗口本身:

public MainWindow()
    {
        InitializeComponent();
        MainWindowNavigation mainWindow = new MainWindowNavigation();
        mainWindow.ChangePage(new Pages.MainWindowPage());
    }

不幸的是,这最终导致System.StackOverflowException.

Unfortunately this ends up with System.StackOverflowException.

创建它的主要原因是我希望能够从mainWindow.Content当前显示的页面中更改mainWindow.Content.

The main reason for creating this is that I want to be able to change the mainWindow.Content from a page which is currently displayed in mainWindow.Content.

我已经审查了MVVM,但我不认为在像这样的小型应用程序中使用它是不值得的,因为我想要做的就是打开一个欢迎页面",然后在侧面有几个按钮.按下mainWindow.Content正确地切换到用户可以输入登录详细信息的页面,然后在登录页面上按下按钮时,我想在成功验证输入的登录详细信息后将mainWindow.Content更改为其他页面./p>

I have already reviewed MVVM but I don't think it is worth using it for a small application like this as all I want it to do is Display a Welcome Page on open, then on the side there will be few buttons. Once pressed the mainWindow.Content correctly changes to a page where a user can enter login detail and then on the button press on the login page I want to change the mainWindow.Content to a different page on successful validation of the login details entered.

推荐答案

使用MVVM绝对可以,因为它将简化您需求的实现.WPF是为与MVVM模式一起使用而构建的,这意味着大量使用了数据绑定和数据模板.

Using MVVM is absolutely fine as it will simplify the implementation of your requirement. WPF is build to be used with the MVVM pattern, which means to make heavy use of data binding and data templates.

任务很简单.为每个视图创建一个 UserControl (或 DataTemplate ),例如, WelcomePage LoginPage 及其相应的视图模型 WelcomePageViewModel LoginPageViewModel .

The task is quite simple. Create a UserControl (or DataTemplate) for each view e.g., WelcomePage and LoginPage with their corresponding view models WelcomePageViewModel and LoginPageViewModel.

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

A ContentControl will display the pages.
The main trick is that, when using an implicit DataTemplate (a template resource without an x:Key defined), the XAML parser will automatically lookup and apply the correct template, where the DataType matches the current content type of a ContentControl. This makes navigation very simple, as you just have to select the current page from a collection of page models and set this page via data binding to the Content property of the ContentControl or ContentPresenter:

MainWindow.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. 创建页面控件.这可以是 Control UserControl Page ,也可以只是 DataTemplate

WelcomePage.xaml

<UserControl>
  <StackPanel>
    <TextBlock Text="{Binding PageTitle}" />
    <TextBlock Text="{Binding Message}" />
  </StackPanel>
</UserControl>

LoginPage.xaml

<UserControl>
  <StackPanel>
    <TextBlock Text="{Binding PageTitle}" />
    <TextBox Text="{Binding UserName}" />
  </StackPanel>
</UserControl>

  • 创建页面模型

  • Create the page models

    IPage.cs

    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#中的魔术字符串)

  • Create an enumeration of page identifiers (to eliminate magic strings in XAML and C#)

    PageName.cs

    public enum PageName
    {
      Undefined = 0, WelcomePage, LoginPage
    }
    

  • 创建 MainViewModel ,它将管理页面及其导航

  • Create the MainViewModel which will manage the pages and their navigation

    MainViewModel.cs
    可以在
    上找到 RelayCommand 的实现. Microsoft Docs:模式-具有Model-View-ViewModel设计模式的WPF应用程序-

    MainViewModel.cs
    An implementation of RelayCommand can be found at
    Microsoft Docs: Patterns - WPF Apps With The Model-View-ViewModel Design Pattern - Relaying Command Logic

    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));
      }
    }
    

  • 这篇关于C#WPF页面导航类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆