# Quick.Framework **Repository Path**: wanglm-code/Quick.Framework ## Basic Information - **Project Name**: Quick.Framework - **Description**: A rapid development framework for WPF. - **Primary Language**: C# - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 25 - **Created**: 2024-07-15 - **Last Updated**: 2024-07-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README **Nuget包地址:** https://www.nuget.org/packages/QuickFramework.Wpf/ 用vs的nuget搜索包时,请勾选“包括预发行版本”,搜索关键字:QuickFramework.Wpf **QQ交流群:196554374** 注:本框架要求.net framework 4.6.1或以上版本,暂不支持.net core和.net 5,6。编译源码需要vs2019或以上版本,当第一次编译提示错误时,在解决方案上右键,点击“清理解决方案”,然后再次编译,即可成功 Table of Contents ================= * [1\.前言](#1前言) * [2\.框架组成](#2框架组成) * [2\.1 \.Net核心扩展](#21-net核心扩展) * [2\.2 模块化和依赖注入](#22-模块化和依赖注入) * [2\.3 日志系统](#23-日志系统) * [2\.4 配置系统](#24-配置系统) * [2\.5 数据库多连接支持](#25-数据库多连接支持) * [2\.6 Dapper ORM](#26-dapper-orm) * [2\.7 Local Storage](#27-local-storage) * [2\.8 对象映射](#28-对象映射) * [2\.9 WPF应用程序](#29-wpf应用程序) * [2\.10 多语言支持](#210-多语言支持) * [2\.11 消息机制](#211-消息机制) * [2\.12 样式增强](#212-样式增强) * [2\.13 扩展控件](#213-扩展控件) * [2\.14 MVVM增强](#214-mvvm增强) * [2\.15 转换器](#215-转换器) * [2\.16 消息框](#216-消息框) * [2\.17 EF支持](#217-ef支持) * [2\.18 自动UI](#218-自动ui) * [3 框架特色](#3-框架特色) * [3\.1 C\#基础扩展](#31-c基础扩展) * [3\.2 MVVM](#32-mvvm) * [3\.2\.1 通知属性编写难](#321-通知属性编写难) * [3\.2\.2 Command编写难](#322-command编写难) * [3\.2\.3 事件绑定难](#323-事件绑定难) * [3\.2\.4 转换器编写难](#324-转换器编写难) * [3\.2\.5 MVVM弹窗难](#325-mvvm弹窗难) * [3\.2\.6 MVVM操作界面难](#326-mvvm操作界面难) * [3\.2\.7 MVVM动画难](#327-mvvm动画难) * [3\.3 ViewModel基础类](#33-viewmodel基础类) * [3\.3\.1 框架提供了多个ViewModel基类:](#331-框架提供了多个viewmodel基类) * [3\.3\.2 核心类QBindableAppBase](#332-核心类qbindableappbase) * [3\.4 LocalStorage](#34-localstorage) * [3\.5 配置系统](#35-配置系统) * [3\.6 WPF应用程序增强](#36-wpf应用程序增强) * [3\.7 消息机制](#37-消息机制) * [3\.8 消息框](#38-消息框) * [3\.9 自动UI](#39-自动ui) * [3\.10 皮肤的集成](#310-皮肤的集成) * [3\.11 布局](#311-布局) # 1.前言 ​ 从事了10多年的.net和WPF开发,用过各种各样的设计模式和框架,包括Prism,Abp等框架,自己也曾根据自己的理解搭建过一些开发框架。各种模式和框架有它的优点,也有缺点,这是很正常的事情,因为众口难调。有些开发者不喜欢层次太多,太复杂,过于考虑扩展性的框架,他们关注点往往是快速开发,希望框架提供很多能直接用的轮子,而不关注框架的扩展性。有些开发者又需要模块和层次足够多,为将来的扩展性留有余地,他们不太在意复杂度和开发速度,而更在于架构的扩展性和灵活性。因此没有一个框架能说是完美的,能满足如此多的开发人员的不同需求。基于多年的经验和走过的路,我常常在想,WPF开发应该用那种架构最为合适,应该提供哪些轮子能使开发变的容易。于是针对开发中的种种痛点,逐渐形成了自己的思路,决定基于已有的一些经验打造一个新的框架。这个新框架同样不可能满足所有的需求,必须基于一些特定的设计目标和设计原则。 ​ Quick框架原则之一是要上手简单,快速开发,尽可能的提供轮子解决WPF开发中的痛点。原则之二是要求开发者遵循框架,但不会将方方面面框死,应该给使用者留有很大自由度,因此不会像领域驱动那样,强迫开发者去用DDD。这个框架不会满足所有人的需求,希望理解它,愿意用的人用之,欢迎提出宝贵意见,不喜欢用的人也不要喷,每个框架的关注重点不一样,还是我上面说的众口难调。即使像Abp框架这样看似强大的框架,也有很多人不买账,它的缺点恰恰就是过于强大,过于解耦,太重了,忽视了开发的便利性。 ​ 另外,本框架使用大量第三方优秀类库作为支撑,因为我认为没必要重复造轮子,很多轮子经过多年的打磨,付出了大量的精力。如果像Prism那样,什么都自己做,我觉得一是没有时间去造,二也造不好。 # 2.框架组成 ![](https://raw.githubusercontent.com/autcn/Quick.Framework/master/README.assets/quick-framework.png) ​ 上图是框架核心的组成,为了便利性和架构的平衡,并没有拆解的太细,而是相对集成,降低复杂度。因此把轻量的Dapper ORM也放到了核心里,而重量级的Entity Framework则单独提供了一个Dll来支持,根据需要进行引用。 ## 2.1 .Net核心扩展 ​ 主要是对一些常用的.Net基础类进行了扩展,比如byte[]转md5,转hex字符串等等, 常用的有判断字符串IsNullOrEmpty(),判断集合IsNullOrEmpty()等,还包括一些常用的TaskScheduler。 ## 2.2 模块化和依赖注入 ​ 模块化和依赖注入是整个框架的核心,尽管有些初学者难以理解这两个概念,但是我认为框架有必要使用这两个机制。模块化有助于架构的清晰,合理,规范化,而依赖注入能提高开发效率和解耦。这里不是为了高大上而用这两个机制,而是为了我们合理架构和快速开发,确实需要模块化和依赖注入机制的支持。对于模块化,参考了Abp框架,它的一个很大优点是模块依赖的概念,解决了依赖注入时因先后顺序不可控导致的问题。对于依赖注入机制,则使用了目前最为流行的Autofac,之所以选择Autofac,因为它提供了足够强大的特性和极高的效率,在业界有很好的口碑,它发展了多年,迭代了很多版本,非常成熟。我认为没有必要像prism那样去自己打造一个并不完善的IOC。 ​ Autofac帮助文档:https://autofac.readthedocs.io/en/latest/getting-started/index.html ## 2.3 日志系统 采用流行的Serilog提供支持,帮助文档:[https://github.com/serilog/serilog/wiki/Getting-Started]() ## 2.4 配置系统 配置文件机制也有各种各样的实现方法,本框架实现基于json的,可读写的配置系统,方便之处在于,标记一个类即可写入配置,并自动全局注入。 ## 2.5 数据库多连接支持 通常来说一个WPF应用程序只访问一个数据库,在访问多个数据库时往往架构比较混乱,本框架提供了一个高度解耦的多数据库机制 ## 2.6 Dapper ORM Dapper作为轻量级的数据库访问类库,深受广大开发者欢迎,本框架封装了一个强大的基于Dapper的ORM库,很容易在框架中进行数据库操作。当然,喜欢Entity Framework的开发者也可以继续使用EF,二者不冲突,甚至可以混合使用(不推荐)。 ## 2.7 Local Storage Local Storage的好处在于,可以随时随地的存储数据,极大提高了便利性,因为很多时候,一些配置和临时数据记录并不会都存放于数据库,开发者也不愿意专门为这些数据单独写存储机制。 ## 2.8 对象映射 本框架使用AutoMapper来做对象映射。历史经验告诉我们,很多业务场景下,Entity与表现层的Dto分离是必要的,否则必将导致业务混乱。而Entity与Dto的转换又是一个非常繁琐的问题,AutoMapper恰恰就是来解决对象转换问题的。 AutoMapper帮助文档:https://docs.automapper.org/en/stable/index.html ## 2.9 WPF应用程序 包括应用单一实例设置,重复启动第二个实例时自动激活第一个,全局异常捕获,崩溃自动写日志等功能。 ## 2.10 多语言支持 界面多语言切换有很多种解决方案,本框架还是采用WPF的DynamicResource机制,因为这个机制在Xaml中使用时是最简单的 ## 2.11 消息机制 ​ 一个实现订阅发布机制的消息总线对于应用来说是非常有用的,提高了解决问题的能力,也能帮助实现一些场景下的解耦。本框架底层以DevExpress.Mvvm 的Messenger为基础实现了消息的发布订阅。这里需要特别说明的是,这类消息机制无一例外都是通过全局中间件来进行通信的,因此向全局容器订阅消息时,将把订阅者的引用注册到全局容器中,尽管使用了弱引用机制,但仍广泛存在垃圾回收不及时的问题。因此这里有两条建议:一是尽量避免在临时对象中注册消息,建议在常驻对象中订阅消息,比如主窗口类,单例服务等。二是如果确需在临时对象中注册消息,记得在对象不用时注销消息订阅,这样能使得引用立即被释放。比如在弹出一个窗口中订阅了消息,那么在窗口关闭时应该注销订阅。 ## 2.12 样式增强 ​ 对于UI控件样式的增强,确实是一个耗费巨大精力和长耗时的工作,因此本框架没有做过多的控件样式增强,开发者可以使用任何第三方UI。Quick框架本身提供了一套简易的UI皮肤,用户可以参照源码,很容易进行重写。 ## 2.13 扩展控件 ​ 本框架提供了一些增强的控件,如:AutoCompleteComboBox,AutoFitTextControl,FilePicker,IPAddressControl,LoadingBox,PageBar,PageGrid,PageItemsControl,RadioSelector,SpaceStackPanel,SpinnerControl等等,同时也增加了对TextBox输入的限制功能。 ## 2.14 MVVM增强 ​ 本框架使用了DevExpress.Mvvm提供的DXEvent, DXBinding, DXCommand三大神器,但并没有使用Dev的WPF框架。本框架以这三个扩展为基础,展示了与众不同的MVVM思路,极大提高了MVVM下开发的便利性,这也是本框架的一个非常大的优势,解决各种MVVM开发中的痛点。 ## 2.15 转换器 ​ 写转换器是令很多WPF开发人员反感的一件事,本框架提供了大量内置转换器,提供了QBinding,UniversalConverter两个强大的语法,再加上Dev的DXBinding的加持,基本告别了写转换器的历史。如果必须要写转换器,那么框架提供了Format机制,使得写转换器非常简单,一个函数即可。 ## 2.16 消息框 ​ MessageBox是WPF开发中一个很重要的角色,本框架重写了MessageBox,提供了设置选项,可以从系统,Handy Control和本框架自己实现的消息框中任选一种。由于Handy Control的消息框存在加载慢和按钮显示延迟问题,不建议使用。 ## 2.17 EF支持 ​ Entity Framework作为一个重量级的数据库访问框架,深受一些开发者喜爱,本框架对EF的支持主要在于提供了ViewModel基类,更规范和方便的调用EF,同时实现了自动UI下的对EF的无感调用。 ## 2.18 自动UI ​ 采用ViewModel属性标记的方式,由ViewModel自动生成UI,极大的减少了Xaml代码量。对于RadioButton组,枚举的绑定问题,框架也提供了完善的解决方案。除此之外,允许开发者自定义标记和编写控件生成器。 # 3 框架特色 ​ 本框架的核心目标是提升开发效率,同时兼顾架构,因此这是一个开发效率与架构平衡的框架,并不会像很多框架那样,为了架构而牺牲开发效率。本节重点介绍提升效率的功能特点,如果你看完本节觉得这些功能确实解决了你的问题,提升了开发效率,那么你可以试用一下这个框架。 ## 3.1 C#基础扩展 string扩展 ``` c# // ------------原写法------------ string name = GetUserName(userId); if( string.IsNullOrEmpty(name) ) { throw new Exception("The user is not found."); } // ++++++++++++扩展写法+++++++++++ if( name.IsNullOrEmpty() ) { } ``` 有些开发者说并没有节省多少代码,但是写多了之后,就会发现用扩展写法还是方便的多,下面列出一些常用的: ``` c# str.IsNullOrEmpty(); str.IsNullOrWhiteSpace(); string[] lines = str.ReadAllLines(); string md5 = str.ToMd5(); byte[] bytes = str.ToHexBytes(); string strLeft = str.Left(5); string strRight = str.Right(5); byte[] utf8 = str.GetBytes(Encoding.UTF8); ``` byte[]扩展 ``` c# byte[] data; string str = data.ToHexString(); string md5 = data.ToMd5UpperString(); ``` IEnumerable扩展 ``` c# // 原写法 List users = GetUsers(); if( user == null || user.Count == 0 ) { throw new Exception("The users are empty!"); } // 扩展写法 if( users.IsNullOrEmpty() ) { } ``` 还有很多其他扩展,不全部列出了 ## 3.2 MVVM 很多新接触 WPF的开发人员,对于MVVM开发特别不适应,他们会觉得各种繁琐,甚至对该模式有所抵触,该节着重介绍本框架的MVVM的理念 ### 3.2.1 通知属性编写难 为了普通类支持绑定,WPF要求类实现INotifyPropertyChanged 接口,每个属性的Set都要写Notify,这是很多开发人员很反感的。 ``` c# // ------------原写法1------------ private string _name; public string Name { get { return _name; } set { if( _name != value ) { _name = value; NotifyPropertyChanged(nameof(Name)); } } } // ------------改进写法2------------ private string _name; public string Name { get => _name; set => SetProperty(ref _name, value); } // ++++++++++++Quick框架写法+++++++++++ public string Name { get; set; } ``` ### 3.2.2 Command编写难 我们知道按钮的执行要绑定到ViewModel,需要在ViewModel中定义ICommand,很多开发人员对此都十分反感,界面几十个按钮,就要写几十遍这个东西 ``` c# // ------------原写法------------