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