.net core/5/6/7中WPF如何優雅的開始開發

2022-11-25 18:02:43

WPF是微軟的.net平臺中的一個桌面使用者端應用程式框架,經常用於企業開發windows桌面使用者端,廣泛應用於中小企業快速開發一款工具,本人也是比較喜歡利用WPF開發一些小工具。

知名案例

1.虎牙直播使用者端
2.西門子醫療上位機
其中西門子醫療的上位機程式稱得上使用WPF技術的極其優秀的專案。(:德國人寫程式碼真的很嚴格工整。
當然西門子的.net還是基於framework,模組之間通訊用的WCF,依賴注入使用的spring.net我在的時候好像準備改成Autofac了。扯遠了~

.net core/5/6/7中開發WPF

伴隨著.net5這個半成品出世,.net framework和core正式合併到一起,在core中也是支援建立WPF模板程式碼的,那麼我們如何在新的平臺下優雅的使用WPF開發一個小工具呢?

MVVM

老的framework我喜歡使用MvvmLightLibs,但是目前用過的都知道該包已經被標記為棄用了,推薦使用微軟的CommunityToolkit.Mvvm,我們可以在專案檔案中新增該包的參照

<PackageReference Include="CommunityToolkit.Mvvm" Version="8.0.0" />

新增好了之後我們將我們的viewmodel繼承ObservableObject具體使用可以看園子裡的一篇文章https://www.cnblogs.com/dino623/p/building_MVVM_programs_using_MVVM_Toolkit.html
範例程式碼:

public class MainWindowViewModel : ObservableObject
    {
        /// <summary>
        /// 屬性變更通知
        /// </summary>
        private Page _currentPage;
        public Page CurrentPage
        {
            get => _currentPage;
            set => SetProperty(ref _currentPage, value);
        }

        //命令繫結
        public RelayCommand ShiftWorkPageCommand { get; set; }
        public RelayCommand OpenWorkSpaceCommand { get; set; }
        }
    }

當然該包還帶了同進程下模組釋出訂閱的實現。本身的事件也支援繫結非同步方法。

DI

常用的依賴注入元件有spring.net,autofac,當然autofac在現在看來也是非常流行強大的。.net一直有一個自帶的依賴注入容器,功能沒有autofac強大,但是一般也夠用。我們需要在專案檔案中匯入微軟提供的相關的包。

<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />

我們會在程式啟動的時候建立一個預設的Host宿主物件,WPF的起始類就是app.cs裡,我們可以覆寫OnStartup方法,在其中啟動一個Host,並且將一些服務註冊進來。如紀錄檔,組態檔,資料庫設定等。

public partial class App : Application
    {
        public static IServiceProvider ServiceProvider;
        protected async override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            var hostbuilder = CreateHostBuilder(e.Args);
            var host = await hostbuilder.StartAsync();
            ServiceProvider = host.Services;
            host.Services.GetRequiredService<MainWindow>()?.Show();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            var hostBuilder = Host.CreateDefaultBuilder(args).UseSerilog((context, logger) =>//註冊Serilog
            {
                logger.ReadFrom.Configuration(context.Configuration);
                logger.Enrich.FromLogContext();
            });
            hostBuilder.ConfigureServices((ctx, services) =>
            {
                services.AddSingleton<MainWindow>();
                services.AddSingleton<MainWindowViewModel>();
            });

            return hostBuilder;
        }
    }

tips :記得把App.xaml中的StartUpUri刪除掉。
上面的程式碼中,我們就註冊了serilog紀錄檔,以及一些我們需要注入的物件,我們可以控制他們的生命週期,關於如何使用.net自帶的依賴注入以及為什麼需要控制反轉可以看這篇網址:https://www.cnblogs.com/youring2/p/10926590.html。

那麼如何使用呢?
我們可以在需要注入的地方通過構造器注入,比如我們的MainWindowViewModel是需要繫結到MainWindow的上下文物件上的,我們可以這樣做:

public partial class MainWindow : Window
    {
        public MainWindow(MainWindowViewModel viewModel)
        {
            InitializeComponent();
            DataContext = viewModel;
        }
    }

這樣程式在範例化MainWindow的時候就會從容器中取到MainWindowViewModel範例放到構造中,不需要我們關心如何去new這樣一個物件。

我們還在App.cs中放了一個靜態的ServiceProvider儲存ServiceProvider的範例,方便我們全域性使用,這是因為有的地方我們不方便構造器的依賴注入,我們就可以利用該物件使用依賴查詢的辦法獲取物件範例:

ServiceProvider.GetRequiredService<MainWindowViewModel>();

Configuration

如何按照上面做的我們在WPF啟動的時候註冊一個預設的Host,那麼也會將設定模組帶入到專案中,我們如何使用設定模組?我們可以在專案根目錄下建立一個appsettings.json檔案,並且右鍵->屬性
設定成這樣

這樣我們就可以使用.net自帶的IConfiguration進行組態檔的讀取。這個IConfiguration也是可以通過構造方法注入的,我們想在程式裡或者組態檔裡這個節點的設定就可以如下操作:


當然了具體更多操作和用法,包括需要根據不同環境區分載入不同的設定以及不喜歡appsettings.json這個名字,想用其他名字都是可以設定的。appsettings.json是他框架預設的組態檔名字,會去找根目錄下這個檔案,如果你沒有設定成其他名字的話。更多設定的操作可以檢視該網址:https://www.cnblogs.com/stulzq/p/8570496.html

結尾

目前為止我們只是介紹了幾個方面的WPF的在.net core/5/6/7中的優雅用法。也是一個基礎的搭建,當然只有一個良好的基礎,一個低耦合,符合規範的基礎才能hold住之後寫程式碼天高任鳥飛的願景哈哈哈哈。
我自己做的一個lol外掛也是使用WPF做的,目前全網下載量破萬,github star 180+,也是基於這些概念開發的,有興趣的小夥伴可以瞭解也好,學習也好。
https://github.com/BruceQiu1996/NPhoenix