狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

【C#】WPF/C#:實現導航功能

admin
2024年7月24日 18:36 本文熱度 754

前言

在WPF中使用導航功能可以使用Frame控件,這是比較基礎的一種方法。前幾天分享了wpfui中NavigationView的基本用法,但是如果真正在項目中使用起來,基礎的用法是無法滿足的。今天通過wpfui中的mvvm例子來說明在wpfui中如何通過依賴注入與MVVM模式使用導航功能。實踐起來,我個人覺得這個例子中實現導航功能還是有點麻煩的,但我也不知道怎么能更優雅,也是學到了一些東西吧。

wpfui中MVVM例子的地址在:https://github.com/lepoco/wpfui/tree/main/src/Wpf.Ui.Demo.Mvvm

實現效果如下所示:

如果你對此感興趣,可以繼續閱讀。

實踐

使用依賴注入

將主窗體與主窗體的ViewModel與每個頁面與每個頁面的ViewModel都存入依賴注入容器中:

當然不只是窗體頁面與ViewModel,也需要注冊一些服務。

為了實現導航功能,使用了兩個服務分別是NavigationService與PageService。

NavigationService在wpfui庫中已經自帶了,直接使用即可:

具體代碼可自行研究,這里就不放了。

而PageService在wpfui中沒有自帶,需要自己定義,MVVM例子中的定義如下所示:

 public class PageService : IPageService
 {
     /// <summary>
     /// Service which provides the instances of pages.
     /// </summary>
     private readonly IServiceProvider _serviceProvider;

     /// <summary>
     /// Initializes a new instance of the <see cref="PageService"/> class and attaches the <see cref="IServiceProvider"/>.
     /// </summary>
     public PageService(IServiceProvider serviceProvider)
     {
         _serviceProvider = serviceProvider;
     }

     /// <inheritdoc />
     public T? GetPage<T>()
         where T : class
     {
         if (!typeof(FrameworkElement).IsAssignableFrom(typeof(T)))
         {
             throw new InvalidOperationException("The page should be a WPF control.");
         }

         return (T?)_serviceProvider.GetService(typeof(T));
     }

     /// <inheritdoc />
     public FrameworkElement? GetPage(Type pageType)
     {
         if (!typeof(FrameworkElement).IsAssignableFrom(pageType))
         {
             throw new InvalidOperationException("The page should be a WPF control.");
         }

         return _serviceProvider.GetService(pageType) as FrameworkElement;
     }
 }

現在已經將所有窗體、頁面、ViewModels與相關服務都注冊到容器中了。

ViewModel

在MainWindowViewModel中將頁面存入一個屬性中:

在非首頁的ViewModel中實現INavigationAware接口:

View

MainWindow.cs如下所示:

 public partial class MainWindow : INavigationWindow
 {
     public ViewModels.MainWindowViewModel ViewModel { get; }

     public MainWindow(
         ViewModels.MainWindowViewModel viewModel,
         IPageService pageService,
         INavigationService navigationService
     
)

     {
         ViewModel = viewModel;
         DataContext = this;

         Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this);

         InitializeComponent();
         SetPageService(pageService);

         navigationService.SetNavigationControl(RootNavigation);
     }

     public INavigationView GetNavigation() => RootNavigation;

     public bool Navigate(Type pageType) => RootNavigation.Navigate(pageType);

     public void SetPageService(IPageService pageService) => RootNavigation.SetPageService(pageService);

     public void ShowWindow() => Show();

     public void CloseWindow() => Close();

     /// <summary>
     /// Raises the closed event.
     /// </summary>
     protected override void OnClosed(EventArgs e)
     {
         base.OnClosed(e);

         // Make sure that closing this window will begin the process of closing the application.
         Application.Current.Shutdown();
     }

     INavigationView INavigationWindow.GetNavigation()
     {
         throw new NotImplementedException();
     }

     public void SetServiceProvider(IServiceProvider serviceProvider)
     {
         throw new NotImplementedException();
     }
 }

首先實現了INavigationWindow接口。在構造函數中注入所需的依賴類。注意這里的RootNavigation其實就是頁面中NavigationView的名稱:

剛開始看這里沒注意到,卡殼了很久。

因為你在代碼中查看定義,它會轉到這個地方:

沒經驗不知道是什么,但是這次過后,知道這是在Xaml中定義,由工具自動生成的代碼了。

其他的頁面改成了這樣的寫法:

 public partial class DashboardPage : INavigableView<DashboardViewModel>
 {
     public DashboardViewModel ViewModel { get; }
     public DashboardPage(DashboardViewModel  viewModel)
     {
         ViewModel = viewModel;
         this.DataContext = this;
         InitializeComponent();          
     }
 }

都實現了INavigableView<out T>接口:

顯示主窗體與主頁面

現在準備工作都做好了,下一步就是顯示主窗體與主頁面了。

在容器中我們也注入了這個:

ApplicationHostService如下所示:

    /// <summary>
    /// Managed host of the application.
    /// </summary>
    public class ApplicationHostService : IHostedService
    {
        private readonly IServiceProvider _serviceProvider;
        private INavigationWindow? _navigationWindow;

        public ApplicationHostService(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// Triggered when the application host is ready to start the service.
        /// </summary>
        /// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            await HandleActivationAsync();
        }

        /// <summary>
        /// Triggered when the application host is performing a graceful shutdown.
        /// </summary>
        /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
        }

        /// <summary>
        /// Creates main window during activation.
        /// </summary>
        private async Task HandleActivationAsync()
        {
            await Task.CompletedTask;

            if (!System.Windows.Application.Current.Windows.OfType<MainWindow>().Any())
            {
                _navigationWindow = (
                    _serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow
                )!;
                _navigationWindow!.ShowWindow();

                _ = _navigationWindow.Navigate(typeof(DashboardPage));
            }

            await Task.CompletedTask;
        }
    }
}

在app.xaml中定義了程序啟動與退出事件的處理程序:

 /// <summary>
 /// Occurs when the application is loading.
 /// </summary>
 private async void OnStartup(object sender, StartupEventArgs e)
 {
     await _host.StartAsync();
 }

 /// <summary>
 /// Occurs when the application is closing.
 /// </summary>
 private async void OnExit(object sender, ExitEventArgs e)
 {
     await _host.StopAsync();

     _host.Dispose();
 }

整個過程回顧

在OnStartup方法中打個斷點,理解這個過程:

點擊下一步:

到ApplicationHostService中了,一步一步調試,注意這個地方:

因為主窗體實現了INavigationWindow接口,這里獲取了主窗體并將主窗體顯示,然后調用主窗體中的Navigate方法,導航到DashPage頁面,之后點繼續,結果如下所示:

最后

以上就是自己最近學習wpfui中導航功能實現的筆記,在自己的項目中也成功使用,對于可能會經常修改代碼增加功能的程序這樣做感覺挺好的,但是如果你只是使用WPF做一個簡單的小工具,感覺這樣做增加了復雜度,不用依賴注入,不用做這么復雜的導航,甚至不使用MVVM模式都可以。


該文章在 2024/7/24 18:36:09 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved