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