【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 前言:在C/S架构上,WPF无疑已经是“桌面一霸”了。在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用。但是WPF也有很多年的历史了,并且基于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

 1995789-20220305121022265-1681252663.png


2、创建完成以后,如下图所示。


1995789-20220305122225592-1798995885.png


3、再新建一个WPF类库项目,用于存放所有第三方nuget包。此处纯个人习惯,用于防止多项目引用包的时候,产生包版本不一致的问题。

 1995789-20220305122300641-930069410.png


4、包项目里面,添加三个核心的包。分别是:Prism.Unity 、   Prism.Unity.Extensions   和  Unity.Microsoft.DependencyInjection  


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

 

1995789-20220305122502654-615143115.png

 

5、WpfDemo项目里面,引用刚刚的包项目后,修改App.xaml文件里面的默认配置项。以下是默认的内容:


1995789-20220305122800073-1920938957.png


6、替换为以下的内容。以下内容代表的是该程序引入prism框架。


1995789-20220305122920109-929569694.png

7、App.cs类里面,继承改为PrismApplication,并且提供几个方法的重写。如果没有重写,可能会提示错误。

 1995789-20220305123200637-311005778.png


8、都载入以后,运行程序,就可以启动画面了。


1995789-20220305125940941-1115922505.png


9、项目新建Views文件夹和ViewModels文件夹。prism框架默认会自动识别存在Views文件夹的为视图端,ViewModels文件夹为VM端,用于自动双向绑定的匹配使用。


并且VM类与Views视图必须名称对应,VM类的结尾必须是xxxViewModel。


先建立一个登录页面,存放于Views文件夹下,然后页面引入prism框架所需的

目录,如图所示。

同时设置了一个页面名称,该名称后面当做参数进行传递使用。


1995789-20220305130033350-161161705.png


10、新建对应Login窗体的VM类 LoginViewModel,并且继承BindbleBase类,用于提供prism的双向绑定功能。


1995789-20220305130429944-886257170.png


11、提供用户名、密码属性,以及用于按钮触发的事件属性。并且提供了一个模拟用户登录的方法。


1995789-20220305130800964-2096781031.png

 

12、在Login.xaml文件下,新增两个输入框和一个按钮,用于模拟用户登录功能和双向绑定功能。Mode=TwoWay的意思是,前端数据变更,会自动同步到后端绑定的属性上;后端绑定的属性如果被修改值了,也会传递到前端进行同步显示。还有其他的Mode,小伙伴们可以自行去尝试。


Command命令用于绑定事件属性,并且提供了一个参数,把当前页面当做参数传入进去,用于页面跳转使用;如果不需要参数的情况下,直接不需要


CommandParameter属性就行。Command命令默认是鼠标单击事件,如果是其他事件需要实现,可以自定义做一些对应的事件的封装来进行实现。


其他说明:任意属性都是可以通过双向绑定进行实现的,包括控件名称、以下label控件的content属性、其他属性等等一系列。大佬们可以自行玩玩,此处提供简单案例,所以只对输入框的Text属性和按钮的点击事件提供了双向绑定的功能。

 

1995789-20220305130916577-1918676153.png

 

13、在App.cs类里面,提供InitializeShell方法的重写,并且注册Login页面。此处可以实现启动时候打开登录页面,通过提供DialogResult属性以后,就可以打开CreateShell方法里面注册的页面了。


1995789-20220305131441238-1506086703.png

 

14、现在运行程序,打开了登录页面,进行验证一下,如下图所示,说明验证生效了。输入正确的用户名和密码就可以进入到MainWindow页面。


1995789-20220305131710972-2037487374.png

 

15、接下来试试依赖注入的使用。先创建一个WPF类库项目,提供一个LoginService类与接口当做服务;并提供UserLogin方法的实现,如下图所示。


1995789-20220305131807965-1336037185.png

 

16、项目引用以后,提供属性注入。属性注入需要使用public,并且是属性,以及添加 Dependency的标记;如果是构造函数注入,则无需这些步骤。然后在登录方法里面,提供注入方法的使用,如下图所示。

 1995789-20220305131942107-1016009913.png


17、在App.cs类里面,先前提供的重写方法 RegisterTypes方法里面,进行服务的注册。


以下提供了一个瞬时生命周期的注入,如下所示。如果要使用其他生命周期,大佬们可以自行研究,都是自带的,我就不多写了。


1995789-20220305132147062-866403238.png


18、最后,运行程序,查看效果,程序运行符合预期,说明使用unity ioc容器进行服务注册成功。


1995789-20220305132440485-1808421540.png

 

19、 后记——有关代码奉上:

App.xaml


<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>

 

App.cs


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)
        {
        }

 

LoginViewModel.cs


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;
        }
    }

 

Login.xaml


<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>

 

LoginService.cs


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

 

以上就是本篇文章的全部内容,欢迎大佬们点赞、评论或转发。如需转发,记得注明出处哟~ 谢谢大家围观。


目录
相关文章
|
容器
.net core Autofac IOC 容器的简单使用
## 书接上回,介绍了[.net core 读取配置文件的几种方式](https://developer.aliyun.com/article/1363340?spm=a2c6h.13148508.setting.14.21764f0ehMR1KI ".net core 读取配置文件的几种方式"),本文学习Autofac的同时再次增加一种读取配置文件的方法。 ## 本文介绍Auofac,一个优秀的.NET IOC框架 ## 源码地址:https://github.com/autofac/Autofac # 1、打开NuGet包管理器安装Autofac.Extensions.Dependenc
141 0
|
容器
.NET Core - Autofac增强容器能力
.NET Core - Autofac增强容器能力
|
5月前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
109 5
|
6月前
|
开发框架 .NET 程序员
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
Autofac 是一个轻量级的依赖注入框架,专门为 .NET 应用程序量身定做,它就像是你代码中的 "魔法师",用它来管理对象的生命周期,让你的代码更加模块化、易于测试和维护
179 4
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
|
7月前
|
设计模式 前端开发 C#
使用 Prism 框架实现导航.NET 6.0 + WPF
使用 Prism 框架实现导航.NET 6.0 + WPF
239 10
|
9月前
|
容器 C# Docker
WPF与容器技术的碰撞:手把手教你Docker化WPF应用,实现跨环境一致性的开发与部署
【8月更文挑战第31天】容器技术简化了软件开发、测试和部署流程,尤其对Windows Presentation Foundation(WPF)应用程序而言,利用Docker能显著提升其可移植性和可维护性。本文通过具体示例代码,详细介绍了如何将WPF应用Docker化的过程,包括创建Dockerfile及构建和运行Docker镜像的步骤。借助容器技术,WPF应用能在任何支持Docker的环境下一致运行,极大地提升了开发效率和部署灵活性。
383 1
|
9月前
|
前端开发 C# 开发者
WPF开发者必读:MVVM模式实战,轻松构建可维护的应用程序,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离关注点,提高了代码的可维护性和可扩展性。本文详细介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定与逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种模式,开发者可以更高效地构建桌面应用程序。希望本文能帮助你在WPF开发中更好地应用MVVM模式。
456 1
|
8月前
|
设计模式 前端开发 C#
WPF 项目中 MVVM模式 的简单例子说明
本文通过WPF项目中的加法操作示例,讲解了MVVM模式的结构和实现方法,包括数据模型、视图、视图模型的创建和数据绑定,以及命令的实现和事件通知机制。
|
9月前
|
前端开发 C# 设计模式
“深度剖析WPF开发中的设计模式应用:以MVVM为核心,手把手教你重构代码结构,实现软件工程的最佳实践与高效协作”
【8月更文挑战第31天】设计模式是在软件工程中解决常见问题的成熟方案。在WPF开发中,合理应用如MVC、MVVM及工厂模式等能显著提升代码质量和可维护性。本文通过具体案例,详细解析了这些模式的实际应用,特别是MVVM模式如何通过分离UI逻辑与业务逻辑,实现视图与模型的松耦合,从而优化代码结构并提高开发效率。通过示例代码展示了从模型定义、视图模型管理到视图展示的全过程,帮助读者更好地理解并应用这些模式。
237 0
|
9月前
|
前端开发 开发者 C#
WPF开发者必读:MVVM模式实战,轻松实现现代桌面应用架构,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离应用程序的逻辑和界面,提高了代码的可维护性和可扩展性。本文介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定和逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种方式,开发者可以构建更加高效和可扩展的桌面应用程序。
437 0