【.NET6+WPF】WPF使用prism框架+Unity IOC容器實現MVVM雙向綁定和依賴注入

前言:在C/S架構上,WPF無疑已經是“桌面一霸”了。在.NET生態環境中,很多小伙伴還在使用Winform開發C/S架構的桌面應用。但是WPF也有很多年的歷史了,并且基于MVVM的開發模式,受到了很多開發者的喜愛。

并且隨著工業化的進展,以及幾年前微軟對.NET平臺的開源,國內大多數企業的工業系統或上位機系統,也慢慢從使用MFC、QT等C++平臺,轉向了.NET平臺。并且.NET平臺上,桌面應用上,WPF由于其獨特的一些特性、以及可以制作動畫、無損圖像等,WPF的占比也越來越高。但是大多數小伙伴可能還是按照開發Winform的傳統思路來開發WPF,所以這篇文章當做是一個使用MVVM模式開發的入門教程,希望大家在開發WPF的過程中,可以享受MVVM雙向綁定的快樂。

本篇文章有關環境說明:

開發環境:VS 2022企業版

.NET版本環境:.NET 6

開發的操作系統環境:Win 10

1、先創建一個WPF應用程序,環境選擇.NET 6

aeef3c92dc75b49357bc2aee726d5896.png

2、創建完成以后,如下圖所示。

654d8723b5934f396dd612d0aaef8156.png

3、再新建一個WPF類庫項目,用于存放所有第三方nuget包。此處純個人習慣,用于防止多項目引用包的時候,產生包版本不一致的問題。

e2fa406f5e045ee965cbd0f393573008.png

4、包項目里面,添加三個核心的包。分別是:Prism.Unity 、? ?Prism.Unity.Extensions ??和? Unity.Microsoft.DependencyInjection ?

其中,Prism.Unity 、? ?Prism.Unity.Extensions ?用于提供基礎的Prism框架有關的環境以及Unity容器。Unity.Microsoft.DependencyInjection ?用于提供可支持屬性注入的方式,如果不使用屬性注入,也可以不使用。

cc5358c87c0d04658441d574449d975f.png

5、WpfDemo項目里面,引用剛剛的包項目后,修改App.xaml文件里面的默認配置項。以下是默認的內容:

42a6d9839313bfe6cf59adf2f4a2c207.png

6、替換為以下的內容。以下內容代表的是該程序引入prism框架。

0605fa0fdaf85b08e5ee5d592ff27c77.png

7、App.cs類里面,繼承改為PrismApplication,并且提供幾個方法的重寫。如果沒有重寫,可能會提示錯誤。

7fe415dd67a0ca93e8bf52bfa43ef551.png

8、都載入以后,運行程序,就可以啟動畫面了。

1628585db68db3805d693aa13e7c89c0.png

9、項目新建Views文件夾和ViewModels文件夾。prism框架默認會自動識別存在Views文件夾的為視圖端,ViewModels文件夾為VM端,用于自動雙向綁定的匹配使用。

并且VM類與Views視圖必須名稱對應,VM類的結尾必須是xxxViewModel。

先建立一個登錄頁面,存放于Views文件夾下,然后頁面引入prism框架所需的目錄,如圖所示。

同時設置了一個頁面名稱,該名稱后面當做參數進行傳遞使用。

d4ee4711dfa2898eeb46da535dfb87bd.png

10、新建對應Login窗體的VM類 LoginViewModel,并且繼承BindbleBase類,用于提供prism的雙向綁定功能。

4dcf4e18d255752b438719b34f50de1c.png

11、提供用戶名、密碼屬性,以及用于按鈕觸發的事件屬性。并且提供了一個模擬用戶登錄的方法。

eae67d4d9251b861ccbf8aff97bab3c0.png

12、在Login.xaml文件下,新增兩個輸入框和一個按鈕,用于模擬用戶登錄功能和雙向綁定功能。Mode=TwoWay的意思是,前端數據變更,會自動同步到后端綁定的屬性上;后端綁定的屬性如果被修改值了,也會傳遞到前端進行同步顯示。還有其他的Mode,小伙伴們可以自行去嘗試。

Command命令用于綁定事件屬性,并且提供了一個參數,把當前頁面當做參數傳入進去,用于頁面跳轉使用;如果不需要參數的情況下,直接不需要CommandParameter屬性就行。Command命令默認是鼠標單擊事件,如果是其他事件需要實現,可以自定義做一些對應的事件的封裝來進行實現。

其他說明:任意屬性都是可以通過雙向綁定進行實現的,包括控件名稱、以下label控件的content屬性、其他屬性等等一系列。大佬們可以自行玩玩,此處提供簡單案例,所以只對輸入框的Text屬性和按鈕的點擊事件提供了雙向綁定的功能。

315ae9b366a6d127e0644d637da32980.png

13、在App.cs類里面,提供InitializeShell方法的重寫,并且注冊Login頁面。此處可以實現啟動時候打開登錄頁面,通過提供DialogResult屬性以后,就可以打開CreateShell方法里面注冊的頁面了。

d4e50ce7412a9258e29a6af837e49d61.png

14、現在運行程序,打開了登錄頁面,進行驗證一下,如下圖所示,說明驗證生效了。輸入正確的用戶名和密碼就可以進入到MainWindow頁面。

9d7ed5ca13906b46b82f5560f21dcf12.png

15、接下來試試依賴注入的使用。先創建一個WPF類庫項目,提供一個LoginService類與接口當做服務;并提供UserLogin方法的實現,如下圖所示。

8cf7c6730766e7e27dcd344979ad4bf3.png

16、項目引用以后,提供屬性注入。屬性注入需要使用public,并且是屬性,以及添加 Dependency的標記;如果是構造函數注入,則無需這些步驟。然后在登錄方法里面,提供注入方法的使用,如下圖所示。

30b5ce2820796f8779b94e78bf616d49.png

17、在App.cs類里面,先前提供的重寫方法 RegisterTypes方法里面,進行服務的注冊。

以下提供了一個瞬時生命周期的注入,如下所示。如果要使用其他生命周期,大佬們可以自行研究,都是自帶的,我就不多寫了。

458e034f96935490a338dc58e1ee2240.png

18、最后,運行程序,查看效果,程序運行符合預期,說明使用unity ioc容器進行服務注冊成功。

bb78ef7d1f4f17e942c4a8425f041a2d.png

19、 后記——有關代碼奉上:

App.xaml?

6cace8d13f79fd12e1aa2159a3d0dc86.jpeg

<prism:PrismApplication x:Class="WpfDemo.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfDemo"xmlns:prism="http://prismlibrary.com/"><Application.Resources></Application.Resources>
</prism:PrismApplication>

f74b7c04778c239669769df06e770846.jpeg

App.cs

240f6dde5e600eb763c0e7e82df9e704.jpeg

public partial class App : PrismApplication  // Application    {        public App() { }        protected override Window CreateShell(){            return Container.Resolve<MainWindow>();}        protected override void InitializeShell(Window shell){            if (Container.Resolve<Login>().ShowDialog() == false){Application.Current?.Shutdown();}            else{                base.InitializeShell(shell);}}        protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<ILoginService, LoginService>();  // 默認是transient注冊}        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog){}

175bbe44cc44b52003a2f97141edb043.jpeg

LoginViewModel.cs

308a3551e3aee1049bb18824813b1953.jpeg

public class LoginViewModel: BindableBase{[Dependency]  // using Unity;public ILoginService _loginService { get; set; }        private string userName="";        private string password="";        public string UserName{            get { return userName; }            set { SetProperty(ref userName, value); }}        public string Password{            get { return password; }            set { SetProperty(ref password, value); }}ICommand? loginCommand;        public ICommand LoginCommand {            get{                if (loginCommand == null){loginCommand = new DelegateCommand<object>(UserLogin);}                return loginCommand;}}        void UserLogin(object obj){            if(!_loginService.UserLogin(this.UserName,this.Password)){MessageBox.Show("用戶名或密碼錯誤");                return;}(obj as Window).DialogResult = true;}}

d04b8ae27bf8964c31e60b79b77381d7.jpeg

Login.xaml

52946957a12d746ede44389cae0edee4.jpeg

<Window x:Class="WpfDemo.Views.Login"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfDemo.Views"xmlns:prism="http://prismlibrary.com/"prism:ViewModelLocator.AutoWireViewModel="True"mc:Ignorable="d" Name="loginWindow"Title="Login"  Height="400" Width="600"><Grid><Label Content="用戶名" HorizontalAlignment="Left" Margin="56,119,0,0" VerticalAlignment="Top"/><Label Content="密碼" HorizontalAlignment="Left" Margin="65,150,0,0" VerticalAlignment="Top"/><TextBox HorizontalAlignment="Left" Margin="112,124,0,0" TextWrapping="Wrap" Text="{Binding UserName,Mode=TwoWay}"  VerticalAlignment="Top" Width="143"/><TextBox HorizontalAlignment="Left" Margin="112,154,0,0" TextWrapping="Wrap" Text="{Binding Password,Mode=TwoWay}"   VerticalAlignment="Top" Width="143"/><Button Content="登錄" HorizontalAlignment="Left" Margin="166,192,0,0" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=loginWindow}"VerticalAlignment="Top" Height="24" Width="89"/></Grid>
</Window>

2dc91e024aed3d143c94e592a4359b57.jpeg

LoginService.cs

6a40f58981ed73a1d643d75d18dc90ba.jpeg

public class LoginService: ILoginService{        public Boolean UserLogin(string userName, string password) {            if(userName =="wesky" && password == "123456"){                return true;}            else{                return false;}}}

dda3e4d5c33f140aa4ff18e57f83afad.jpeg

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284092.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284092.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284092.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sql 中 limit 與 limit,offset連用的區別

① select * from table limit 2,1; #跳過2條取出1條數據&#xff0c;limit后面是從第2條開始讀&#xff0c;讀取1條信息&#xff0c;即讀取第3條數據 ② select * from table limit 2 offset 1; #從第1條&#xff08;不包括&#xff09;數據開始取出2條…

【ArcGIS Pro微課1000例】0022:基于DEM進行流域分析生成流域圖

文章目錄 一、填洼二、流向分析三、計算流域一、填洼 填洼Fill,在進行水文分析后續操作前,首先要對DEM進行填洼,創建無凹陷點的DEM。 填洼需要使用水文分析工具下的【填洼】。 確定輸入與輸出即可。 填洼結果: 二、流向分析 在ArcGIS中使用的是八方向流量建模(D8算法),工…

Spring配置文件中bean標簽的scope屬性

轉自&#xff1a;https://fj-sh-chz.iteye.com/blog/1775149 singleton &#xff08;默認屬性&#xff09; Spring將Bean放入Spring IOC容器的緩存池中&#xff0c;并將Bean引用返回給調用者&#xff0c;spring IOC繼續對這些Bean進行后續的生命管理。BeanFactory只管理一個共…

[轉]Druid概述

目錄 1.Apache Druid簡介 2.Apache Druid架構 2.1 服務器類型 2.1.1 Master Server 2.1.2 Query 2.1.3 Data Server 2.2 外部依賴 2.2.1 Deep Storage 2.2.2 Metadata Storage 2.2.3 Zookeeper 2.3 存儲設計 3.在HDP上安裝Apache Druid 3.1 準備數據庫 3.2 安裝…

在 .NET MAUI 中如何更好地自定義控件

點擊上方藍字關注我們&#xff08;本文閱讀時間&#xff1a;10分鐘)今天&#xff0c;我想談談并向您展示在.NET MAUI中完全自定義控件的方法。在查看 .NET MAUI 之前&#xff0c;讓我們回到幾年前&#xff0c;回到 Xamarin.Forms 時代。那時&#xff0c;我們有很多自定義控件的…

【GlobalMapper精品教程】036:基于DEM的流域計算生成流域圖

Globalmapper基于DEM的流域計算生成流域圖教程。 文章目錄一、加載DEM二、流域分析一、加載DEM 加載配套實驗數據。 二、流域分析 GM中的流域分析工具位于分析→生成流域&#xff0c;如下所示&#xff1a; 參數設置如下&#xff1a; 流域計算結果&#xff1a;

html之file標簽 --- 圖片上傳前預覽 -- FileReader

記得以前做網站時&#xff0c;曾經需要實現一個圖片上傳到服務器前&#xff0c;先預覽的功能。當時用html的<input type"file"/>標簽一直實現不了&#xff0c;最后舍棄了這個標簽&#xff0c;使用了其他方式來實現了這個功能。 今天無意發現了一個知識點&#…

Android Studio3.0簡介

Android Studio 3.0.0 Android Studio 3.0.0 (2017年10月)是一個主要版本&#xff0c;包括各種新功能和改進 Android插件的Gradle 3.0.0 ? 支持Android 8.0 ? 支持Java 8庫和Java 8語言功能&#xff08;沒有Jack編譯器&#xff09; ? 支持Android測試支持庫1.0&#xff08;A…

嵌入式linux面試題解析(二)——C語言部分三

嵌入式linux面試題解析&#xff08;二&#xff09;——C語言部分三1、下面的程序會出現什么結果#include <stdio.h>#include <stdlib.h>#include <string.h>void getmemory(char *p){ p(char *) malloc(100); strcpy(p,”hello world”);}int main( ){…

什么是JavaBean、Bean? 什么是POJO、PO、DTO、VO、BO ? 什么是EJB、EntityBean?

前言&#xff1a; 在Java開發中經常遇到這些概念問題&#xff0c;有的可能理解混淆&#xff0c;有的可能理解不到位&#xff0c;特此花了很多時間理順了這些概念。不過有些概念實際開發中并沒有使用到&#xff0c;可能理解還不夠準確&#xff0c;只能靠后續不斷糾正了。 1、什么…

【GlobalMapper精品教程】037:構建泰森多邊形(Thiessen Polygon)實例精解

泰森多邊形是進行快速插值和分析地理實體影響區域的常用工具。例如,用離散點的性質描述多邊形區域的性質,用離散點的數據計算泰森多邊形區域的數據。泰森多邊形可用于定性分析、統計分析和臨近分析等。 文章目錄 一、泰森多邊形的概念二、泰森多邊形的特點三、泰森多邊形構建…

WPF 實現 Gitee 泡泡菜單「完」

WPF 實現 Gitee 泡泡菜單「完」氣泡菜單「完」作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&#xff1b;需要實現泡泡菜單需…

BZOJ 4516: [Sdoi2016]生成魔咒 [后綴自動機]

4516: [Sdoi2016]生成魔咒 題意&#xff1a;詢問一個字符串每個前綴有多少不同的子串 做了一下SDOI2016R1D2&#xff0c;題好水啊隨便AK 強行開map上SAM 每個狀態的貢獻就是\(Max(s)-Min(s)1\) 插入的時候維護一下就行了 #include <iostream> #include <cstdio> #i…

Fiddler抓包5-接口測試(Composer)

前言 Fiddler最大的優勢在于抓包&#xff0c;我們大部分使用的功能也在抓包的功能上&#xff0c;fiddler做接口測試也是非常方便的。 對應沒有接口測試文檔的時候&#xff0c;可以直接抓完包后&#xff0c;copy請求參數&#xff0c;修改下就可以了。 一、Composer簡介 點開右側…

【GlobalMapper精品教程】038:模擬水位上升(洪水淹沒分析)案例教程

基于數字高程模型 ( DEM )格網模型,實現給定水深情況下洪水淹沒區的計算模型,討論洪水淹沒演進過程可視化實現的關鍵技術,以三維可視化方式,動態而形象地模擬在指定洪水水位下的洪水淹沒演進過程。 文章目錄 一、洪水淹沒效果二、洪水淹沒實現三、查詢淹沒區域面積參考教程…

【.NET6+Avalonia】開發支持跨平臺的仿WPF應用程序以及基于ubuntu系統的演示

前言&#xff1a;隨著跨平臺越來越流行&#xff0c;.net core支持跨平臺至今也有好幾年的光景了。但是目前基于.net的跨平臺&#xff0c;大多數還是在使用B/S架構的跨平臺上&#xff1b;至于C/S架構&#xff0c;大部分人可能會選擇QT進行開發&#xff0c;或者很早之前還有一款M…

SOA架構和MSA架構之間的關系

目錄 一、傳統架構&#xff1a;簡單單體模式 二、分布式架構&#xff1a;面向服務架構&#xff08;SOA&#xff09; 1、服務與SOA 2、SOA戰略 3、SOA的兩大基石&#xff1a;RPC和MQ 三、分布式架構&#xff1a;微服務架構&#xff08;MSA&#xff09; 什么是微服務 微服…

Linux系統文件與目錄權限管理

Linux文件目錄權限管理 一、Linux文件屬性及權限 1、Linux文件及目錄權限及屬性說明 &#xff08;1&#xff09;權限及屬性說明 &#xff08;2&#xff09;文件權限說明 三種權限說明&#xff1a;r 讀 read w 寫 write x 執行 excute 2、修改文件屬主及屬組 &#xff08;1&am…

一個文本分詞程序

WordMap類從分詞庫中讀入分詞 將分詞存入unordered_map<std::string, int> 中 #pragma once #include<istream> #include<unordered_map> #include<string> #include<ctime> class WordMap { public:WordMap(const std::string& filename);…

scala學習手記28 - Execute Around模式

我們訪問資源需要關注對資源的鎖定、對資源的申請和釋放&#xff0c;還有考慮可能遇到的各種異常。這些事項本身與代碼的邏輯操作無關&#xff0c;但我們不能遺漏。也就是說進入方法時獲取資源&#xff0c;退出方法時釋放資源。這種處理就進入了Execute Around模式的范疇。 在s…