WPF是微軟的.net平臺中的一個桌面使用者端應用程式框架,經常用於企業開發windows桌面使用者端,廣泛應用於中小企業快速開發一款工具,本人也是比較喜歡利用WPF開發一些小工具。
1.虎牙直播使用者端
2.西門子醫療上位機
其中西門子醫療的上位機程式稱得上使用WPF技術的極其優秀的專案。(:德國人寫程式碼真的很嚴格工整。
當然西門子的.net還是基於framework,模組之間通訊用的WCF,依賴注入使用的spring.net我在的時候好像準備改成Autofac了。扯遠了~
伴隨著.net5這個半成品出世,.net framework和core正式合併到一起,在core中也是支援建立WPF模板程式碼的,那麼我們如何在新的平臺下優雅的使用WPF開發一個小工具呢?
老的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; }
}
}
當然該包還帶了同進程下模組釋出訂閱的實現。本身的事件也支援繫結非同步方法。
常用的依賴注入元件有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>();
如何按照上面做的我們在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