如果您对WinForm应用实战开发指南-如何完成工作流模块的业务表单开发?和winform工作流控件感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解WinForm应用实战开发指南-如何完成工作流
如果您对WinForm应用实战开发指南 - 如何完成工作流模块的业务表单开发?和winform工作流控件感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解WinForm应用实战开发指南 - 如何完成工作流模块的业务表单开发?的各种细节,并对winform工作流控件进行深入的分析,此外还有关于.net – 不知道如何使用WinForm应用程序的依赖注入存储库模式工作模式单元、Appium自动化测试实战开发指南、C# 对WinForm应用程序的App.config的使用及加密、DevExpress WinForm应用开发如何利用MVVM设计模式?这里有答案的实用技巧。
本文目录一览:- WinForm应用实战开发指南 - 如何完成工作流模块的业务表单开发?(winform工作流控件)
- .net – 不知道如何使用WinForm应用程序的依赖注入存储库模式工作模式单元
- Appium自动化测试实战开发指南
- C# 对WinForm应用程序的App.config的使用及加密
- DevExpress WinForm应用开发如何利用MVVM设计模式?这里有答案
WinForm应用实战开发指南 - 如何完成工作流模块的业务表单开发?(winform工作流控件)
在我们开发工作流的时候,往往需要涉及到具体业务表单信息的编辑,有些是采用动态编辑的,有些则是在开发过程中处理的,各有各的优点,动态编辑的则方便维护各种各样的表单,但是数据的绑定及处理则比较麻烦,而自定义开发的,则数据弹性很大,方便修改调整。本篇随笔基于表单的开发设计过程,介绍在工作流中如何新增一个业务表单,以便快速的实现审批业务的上线处理。
PS:给大家推荐这个WinForm应用界面开发组件——DevExpress WinForms,它能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!
DevExpress技术交流群7:674691612 欢迎一起进群讨论
业务表单的基类继承
首先我们来了解一下业务表单的对应关系,一般创建一个业务流程处理,都需要有一个具体的创建业务表单的界面,以及一个查看处理表单的界面。

为了方便,我们尽可能减少代码编写,我们需要把大多数的逻辑处理放在基类实现,这样我们在新增一个业务表单的时候就可以减少很多代码编写及维护了。

如对于FrmAddApply类定义如下,我们定义一些抽象接口用于下面的业务表单实现:
/// <summary> /// 创建申请单的窗体基类 /// </summary> public partial class FrmAddApply : BaseForm { /// <summary> /// 表单ID /// </summary> public string FormID { get; set; } /// <summary> /// 申请单ID /// </summary> public string ApplyId { get; set; } public FrmAddApply() { InitializeComponent(); } /// <summary> /// 显示数据的函数(子类必须实现) /// </summary> public virtual void DisplayData() { } /// <summary> /// 实现控件输入检查的函数(子类必须实现) /// </summary> /// <returns></returns> public virtual bool CheckInput() { return true; } /// <summary> /// 编辑状态下的数据保存(子类必须实现) /// </summary> /// <returns></returns> public virtual bool SaveUpdated() { return true; } /// <summary> /// 新增状态下的数据保存(子类必须实现) /// </summary> /// <returns></returns> public virtual bool SaveAddNew() { return true; } ...................
这样我们创建一个新的业务表单,只需要利用代码生成工具,生成所需要的各层框架代码,然后再生成Winform窗体代码,复制部分界面处理代码过来这个业务表单的子类即可。
下面是一个请假申请的业务表单设计,如下所示。

我们看到这个表单可以使用代码生成工具Database2Sharp快速生成后进行一定调整的,而这个编辑表单的界面,我们只需要使用自动生成的部分代码即可。
相关代码只需要复制上面的新增、更新、显示数据的代码即可。

对于查看申请单的基类FrmViewApply类,我们更加简单,我们需要把它的自定义界面控件加载出来即可。
下面是查看申请单的基类,封装了相关的处理逻辑。
/// <summary> /// 本窗体是通用的查看申请单界面基类。 /// 为减少开发相关页面的工作量,只需要创建一个新窗体,并继承本窗体,然后在子窗体Form_Load函数里面,初始化对应的申请单显示控件即可。 /// </summary> public partial class FrmViewApply : BaseDock { /// <summary> /// 申请单ID /// </summary> public string ApplyId { get; set; } /// <summary> /// 申请单自定义控件 /// </summary> public BaseUserControl ApplyControl { get; set; } /// <summary> /// 默认构造函数 /// </summary> public FrmViewApply() { InitializeComponent(); } private void FrmViewApply_Load(object sender, EventArgs e) { if (!this.DesignMode) { InitToolBar(); } } /// <summary> /// 初始化申请单控件 /// </summary> protected virtual void InitApplyControl(BaseUserControl control) { if (control != null) { this.ApplyControl = control; this.ApplyControl.Dock = DockStyle.Fill; this.Controls.Add(control); } } /// <summary> /// 打印申请单控件内容(默认调用窗体打印) /// </summary> protected virtual void PrintApplyControl() { if(this.ApplyControl != null) { PrintFormHelper.Print(this.ApplyControl, false); } } /// <summary> /// 表单另存为 /// </summary> protected virtual void ApplySaveAs() { } /// <summary> /// 初始化工具栏的按钮和状态 /// </summary> protected virtual void InitToolBar() { ................//基类实现,控制什么时候该做什么审批处理,以及一些常见按钮 } .................
查看请假申请单的窗口就是继承这个FrmViewApply即可,如下所示。
/// <summary> /// 查看请假申请单的窗体 /// </summary> public partial class FrmViewLeave : FrmViewApply { private LeaveControl control = null; public FrmViewLeave() { InitializeComponent(); } private void FrmViewLeave_Load(object sender, EventArgs e) { //初始化控件并展示在基类窗体里面 control = new LeaveControl(); control.ApplyId = this.ApplyId; control.DisplayData(); base.InitApplyControl(control); } }
这个就是全部的窗体源码了,主要的内容我们看到是在LeaveControl这个用户控件类里面的了,
而这个控件主要就是上面编辑请假申请单的界面设计,并复制相关的显示数据代码即可。

相关界面代码如下所示。
/// <summary> /// 查看请假申请单的内容显示控件 /// </summary> public partial class LeaveControl : BaseUserControl { /// <summary> /// 申请单ID /// </summary> public string ApplyId { get; set; } public LeaveControl() { InitializeComponent(); SetReadOnly(); } /// <summary> /// 设置整个窗体布局为只读并设置只读的背景颜色 /// </summary> private void SetReadOnly() { this.layoutControl1.OptionsView.IsReadOnly = DevExpress.Utils.DefaultBoolean.True; this.layoutControl1.Appearance.ControlReadOnly.BackColor = Color.SeaShell; } private void LeaveControl_Load(object sender, EventArgs e) { this.applyInfoControl1.ApplyId = this.ApplyId; this.applyInfoControl1.BindData(); } /// <summary> /// 初始化数据字典 /// </summary> private void InitDictItem() { //初始化代码 } /// <summary> /// 数据显示的函数 /// </summary> public void DisplayData() { InitDictItem();//数据字典加载(公用) //由于申请单一般是用申请表单入口,而非业务数据表,因此只能传入ApplyId获取信息 if (!string.IsNullOrEmpty(ApplyId)) { .................... }
通过上面定义的对应表单的窗体基类,可以减少我们重复编码的需要,我们只需要利用最有效率的生成界面,然后复制代码后调整即可快速生成我们所需要的不同表单界面。
每个表单我们放在一个目录上,这样我们就可以很好管理它们了。

业务表单的动态展示处理
上面介绍了业务表单的填写、查看两个不同的窗口,我们在申请单的审批界面里面,统一显示不同的表单,以及创建不同的业务表单界面,这种动态的处理可以实现不同业务表单的创建及显示界面。
如我的审批工作中,表单的显示界面如下所示,查看具体表单后,可以动态展示不同的业务窗口界面。

另外我们在创建业务表单的时候,根据数据库的配置信息,动态展示所有可以展示的创建入口,单击相关的按钮,可以动态调用创建对应的表单界面。
创建流程业务表单的入口如下所示。

在我的审批工作界面,动态创建对应的查看表单窗体代码如下所示。
/// <summary> /// 分页控件编辑项操作 /// </summary> private void winGridViewPager1_OnEditSelected(object sender, EventArgs e) { //获取记录ID和表单ID string ID = this.winGridViewPager1.gridView1.GetFocusedRowCellDisplayText("ID"); string FormId = string.Concat(this.winGridViewPager1.gridView1.GetFocusedRowCellValue("FormId")); if (!string.IsNullOrEmpty(ID) && !string.IsNullOrEmpty(FormId)) { var formInfo = BLLFactory<BLL.Form>.Instance.FindByID(FormId); if (formInfo != null && !string.IsNullOrEmpty(formInfo.ApplyWin2)) { try { //根据配置的查看窗体,动态构建查看申请单对象 FrmViewApply dlg = Assembly.GetExecutingAssembly().CreateInstance(formInfo.ApplyWin2) as FrmViewApply; if (dlg != null) { dlg.ApplyId = ID; dlg.OnDataSaved += new EventHandler(dlg_OnDataSaved); if (DialogResult.OK == dlg.ShowDialog()) { BindData(); } } } catch (Exception ex) { LogHelper.Error(ex); MessageDxUtil.ShowError(ex.Message); } } } }
这个代码替代了需要手动创建不同对象的处理。
var dlg = new FrmViewAssignWork(); dlg.ApplyId = ID; dlg.OnDataSaved += new EventHandler(dlg_OnDataSaved); if (DialogResult.OK == dlg.ShowDialog()) { BindData(); }
同理,对于创建编辑界面,我们也可以同样的方法动态创建相关的编辑表单界面,如下代码所示。

本文转载自:博客园 - 伍华聪
更多DevExpress线上公开课、中文教程资讯请上中文网获取
.net – 不知道如何使用WinForm应用程序的依赖注入存储库模式工作模式单元
概要
使用依赖注入与我的Winfor应用程序正在创建大量的Repository上下文.我不知道我使用的方式是对还是错,或常见的做法是什么.
细节
在过去的6个月中,我一直在使用存储库模式来构建单元O工作模式的ASP.NET MVC应用程序.除此之外,我一直在使用依赖注入对所有这些Web应用程序取得一些成功.
所以这是我连接我的仓库的一个例子.
public EntityFrameworkRepositoryRegistry() { For<IUnitOfWork>() .HybridHttpOrThreadLocalScoped() // Lifecycle of the object. .Use<sqlServerContext>() // My EF Context. .Ctor<string>("connectionString").Is("name=sqlServer_EF") .Ctor<string>("defaultContainerName").Is("Entities"); // Ayende's EFProf application :) EntityFrameworkProfiler.Initialize(); Scan(x => { x.TheCallingAssembly(); x.ExcludeNamespaceContainingType<Fake.FakeContext>(); x.WithDefaultConventions(); } ); }
好的 – 很棒
这里要注意的主要内容是
>我假设生命周期是Web方案中正确的.
>上下文只会存在一次,每个REQUEST命中
网络服务器.
KEWL.
现在,对于我的WinForm应用程序,我最初创建了一个单一的
单位工作对象(没有依赖注入,只是),并不断传递那个宝宝
所有的服务(然后到仓库).
对于这个win应用程序,它会点击DB查找所有的文本
需要解析的文件(例如25个文件).然后,对于每个文件,它
创建一个新的解析器,读取每一行并将解析的数据插入
一个db表.精细.
问题是,这个构想在所有的分析者中都是分享的
正在严重地扔掉了整个商店的错误.
所以我添加了一些依赖注入,并使用上面的注册表代码.排序相同的事情 – 很多严重的错误.这是因为单个线程再次创建了一个上下文 – > winform.
所以,我现在调整了上下文注册表如下:
public EntityFrameworkRepositoryRegistry(bool isForTheWeb) { if (isForTheWeb) { For<IUnitOfWork>() .HybridHttpOrThreadLocalScoped() .Use<sqlServerContext>() .Ctor<string>("connectionString").Is("name=sqlServer_EF") .Ctor<string>("defaultContainerName").Is("Entities"); } else { For<IUnitOfWork>() .Use<sqlServerContext>() .Ctor<string>("connectionString").Is("name=sqlServer_EF") .Ctor<string>("defaultContainerName").Is("Entities"); } EntityFrameworkProfiler.Initialize(); Scan(x => { x.TheCallingAssembly(); x.ExcludeNamespaceContainingType<Fake.FakeContext>(); x.WithDefaultConventions(); }); }
所以对于WinForm应用程序,它现在不设置生命周期.这个
然后创建了大约160左右的上下文我想! (但它没有真的
错误,或者).
所以,我不知道这是否是正确的做事方式.
所以我的应用程序实际上有25个不同的计时器来检查文件
每…说.. 10秒如果有新的数据,它解析它.
否则,在10秒钟内回来.
这些文件中的每一个都被解析,是否是自己的线程?
然后为每个线程创建一个上下文? (我觉得是类似的
Web场景).还是这样吗?我知道这是很多的上下文,但是
每个上下文并不意味着与数据库的直接连接
连接池,这不应该真的是一个问题.
它有这么多背景的原因是因为如下
代码…(和这些是一些单独的构造函数
存储库类…)
public sqlServerContext(string,string); public GameFileRepository (IUnitOfWork); public LogEntryRepository(IUnitOfWork); public AlertRepository(IUnitOfWork); ... etc..
并为主要服务…
public PunkBusterParser(IUnitOfWork,IGameFileRepositry,ILogEntryRepository,ILoggingService);
所以服务需要一个UoW,每个存储库也都需要
一个..这意味着每个都创建一个新的.
我确定我没有正确地结构化…
任何建议都会真诚感谢!
Appium自动化测试实战开发指南
背景
在当今快速发展的互联网时代,UI 需求越来越大、越来越高大上、越来越复杂,相对应的 App 作为最重要的大前端的一部分,也不可避免。
App 迭代的不断加速,需求的不断复杂化,给测试人员增加了非常大的工作量,但是没办法,测试是保证产品质量的一道非常重要的关卡,只有通过这道关卡,产品的质量才能得到真正的提高。
自动化测试
但是随着 App 的需求复杂化,测试人员似乎已经没有很多精力去应对这一场景,所以自动化测试就出世了,让机器来帮我们做大量的、复杂的、重复的测试工作,是现在测试的趋势。
选择正确的自动化测试工具,也是一件非常重要的事情。
Appium 自动化测试
Appium 是什么
Appium 是一个开源测试自动化框架,可用于本地、混合和移动 web 应用程序。 它使用 WebDriver 协议驱动 iOS、Android 和 Windows 应用程序。可以用于做自动化测试。
用例规则
- 一个脚本对应一个测试的场景
- 只做功能正向逻辑的验证,尽量不做逆向逻辑的验证
- 脚本和脚本直接不要互相依赖
Excel 编写测试用例
- id:测试用例的 id
- title:测试用例的标题
- data:测试用例用到的数据
- result:测试用例测试的结果
- actual:测试用例运行结果,成功或者失败
OpenPyXI 读取数据
编写完 Excel 表格,我们需要使用 Python 的 OpenPyXI 对 Excel 表格进行读取解析:
def get_cases(self, sheet_name):
sheet_name=sheet_name
sheet=self.workbook[sheet_name]
max_row=sheet.max_row
cases=[]
for r in range(2, max_row + 1):
case=Case()
case.id=sheet.cell(row=r,column=1).value
case.title=sheet.cell(row=r,column=2).value
case.data=sheet.cell(row=r,column=3).value
case.expacted=sheet.cell(row=r,column=4).value
cases.expacted=sheet.cell(row=r,column=4).value
cases.append(case)
if type(case.data) == str
case.data = json.loads(case.data)
return cases
测试结果写入 Excel
当测试完成之后,需要把测试的结果写入到 Excel:
def write_result(self,sheet_name,row,result,actual=None):
sheet=self.workbook[sheet_name]
sheet.cell(row,5).value=result
sheet.cell(row,6).value=actual
self.workbook.save(filename=self.file_name)
获取元素定位
测试用例设计完,我们需要执行,我们需要自动化测试操作页面上的元素,所以我们得获取元素。
获取到了元素的位置。
获取元素定位的一些参数,有:
- ID 定位:find_element_by_id()
- class 定位:find_element_by_class_name()
- 文本定位:find_element_by_android_uiautomator()
- xpath 定位:find_element_by_xpath()
使用 unittest 进行断言
unittest 的主要语法包括:
- TestCase
- TestSuite
- TestRunner
- TestLoader
- Fixture
来个小案例:实现一个测试用例,测试一个加法函数
TestCase
TestCase 就是测试用例的意思。
import unittest
def add(x, y):
return x + y
class Test01(unittest.TestCase):
def testadd01(self):
add(2, 3)
def testadd02(self):
add(10, 10)
# testing.....
unittest.main("test01_testcase")
TestSuite & TextTestRunner
- TestSuite 是测试套件,可以批量执行测试用例
- TextTestRunner 是用来执行 测试套件 的
import unittest
from Unittest import Test01
suite = unittest.TestSuite()
suite.addTest(Test01("testadd01"))
# testing......
runner = unittest.TextTestRunner()
runner.run(suite)
TestLoader
TestLoader 可以执行多个测试文件(查找 test 开头的 .py 测试文件)。
现在有个小案例:
运行 tests 目录下 test1.py~test5.py
文件。
import unittest
suite = unittest.defaultTestLoader.discover("../tests")
unittest.TextTestRunner().run(suite)
使用 Apifox 进行 API 自动化测试
那么测试完 UI 界面之后,我们如何更好地去单独测试 API 层面呢?我们需要借助一些比较出色的 API 工具去进行测试,比如 Apifox。
创建 API 请求
我们需要先创建一个 API 请求,填入路径、名称、请求方法。
编写断言脚本
接着我们到 后置脚本 中,选择自定义脚本。
Apifox 已经为我们提供了现成的脚本语句,我这里想要判断返回的 status code 是否为 200。
然后点击保存按钮,即可成功创建请求。
运行得到响应和断言结果
到运行页,点击发送按钮,则可得到响应,以及断言结果。
知识扩展
- UI自动化测试框架比较
- 有什么方法可以自动生成自动化测试报告?
C# 对WinForm应用程序的App.config的使用及加密
C# 对WinForm应用程序的App.config的使用及加密
2013-08-06 14:21:14| 分类: Visual Studio 20 | 标签:.net 部署 配置文件 |举报|字号 订阅
下载LOFTER客户端
我们在写C#应用程序时,在工程文件中放置一个app.config,程序打包时,系统会将该配置文件自动编译为与程序集同名的.exe.config 文件。作用就是应用程序安装后,只需在安装目录中找到该文件,需改字符串内容,就可以改变运行参数,而不用修改源程序代码。例如:可以使用配置文件保存数据库连接字符串;在应用程序中显示变动的文字信息等等。
因为对其使用方法的不了解,大多数人选择了自己重建配置文件并自行管理,实际上这个文件是可以被用户操作的。App.config文件为Xml文档格式,可在文件中添加任意数量的字符串,应用程序在运行时可以读取这些字符串。
一、操作攻略
1. 向项目添加app.config文件:
右击项目名称,选择“添加”→“添加新建项”,在出现的“添加新项”对话框中,选择“添加应用程序配置文件”;如果项目以前没有配置文件,则默认的文件名称为“app.config”,单击“确定”。出现在设计器视图中的app.config文件为:
<?xmlversion="1.0"encoding="utf-8" ?>
<configuration>
</configuration>
在项目进行编译后,在bin\Debuge文件下,将出现两个配置文件(以本项目为例),一个名为“JxcManagement.EXE.config”,另一个名为“JxcManagement.vshost.exe.config”。第一个文件为项目实际使用的配置文件,在程序运行中所做的更改都将被保存于此;第二个文件为原代码“app.config”的同步文件,在程序运行中不会发生更改。
2. connectionStrings配置节:
请注意:如果您的SQL版本为2005 Express版,则默认安装时SQL服务器实例名为localhost\SQLExpress,须更改以下实例中“Data Source=localhost;”一句为“Data Source=localhost\SQLExpress;”,在等于号的两边不要加上空格。
<!--数据库连接串-->
<connectionStrings>
<clear />
<addname="conJxcBook"
connectionString="Data Source=localhost;Initial Catalog=jxcbook;User ID=sa;password=********"providerName="System.Data.SqlClient" />
</connectionStrings>
3. appSettings配置节:
appSettings配置节为整个程序的配置,如果是对当前用户的配置,请使用userSettings配置节,其格式与以下配置书写要求一样。
<!--进销存管理系统初始化需要的参数-->
<appSettings>
<clear />
<addkey="userName"value="" />
<addkey="password"value="" />
<addkey="Department"value="" />
<addkey="returnValue"value="" />
<addkey="pwdPattern"value="" />
<addkey="userPattern"value="" />
</appSettings>
4.读取与更新app.config
对于app.config文件的读写,参照了网络文章:http://www.codeproject.com/csharp/ SystemConfiguration.asp标题为“Read/Write App.Config File with .NET 2.0”一文。请注意:要使用以下的代码访问app.config文件,除添加引用System.Configuration外,还必须在项目添加对System.Configuration.dll的引用。
4.1 读取connectionStrings配置节
///<summary>
///依据连接串名字connectionName返回数据连接字符串
///</summary>
///<param name="connectionName"></param>
///<returns></returns>
private static string GetConnectionStringsConfig(string connectionName)
{
string connectionString =ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString();
Console.WriteLine(connectionString);
return connectionString;
}
4.2 更新connectionStrings配置节
///<summary>
///更新连接字符串
///</summary>
///<param name="newName">连接字符串名称</param>
///<param name="newConString">连接字符串内容</param>
///<param name="newProviderName">数据提供程序名称</param>
private static void UpdateConnectionStringsConfig(string newName,string newConString,string newProviderName)
{
bool isModified = false; //记录该连接串是否已经存在
//如果要更改的连接串已经存在
if (ConfigurationManager.ConnectionStrings[newName] != null)isModified = true;
//新建一个连接字符串实例
ConnectionStringSettings mySettings =new ConnectionStringSettings(newName, newConString, newProviderName);
// 打开可执行的配置文件*.exe.config
Configuration config =ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// 如果连接串已存在,首先删除它
if (isModified)config.ConnectionStrings.ConnectionStrings.Remove(newName);
// 将新的连接串添加到配置文件中.
config.ConnectionStrings.ConnectionStrings.Add(mySettings);
// 保存对配置文件所作的更改
config.Save(ConfigurationSaveMode.Modified);
// 强制重新载入配置文件的ConnectionStrings配置节
ConfigurationManager.RefreshSection("ConnectionStrings");
}
4.3 读取appStrings配置节
///<summary>
///返回*.exe.config文件中appSettings配置节的value项
///</summary>
///<param name="strKey"></param>
///<returns></returns>
private static string GetAppConfig(string strKey)
{
foreach (string key in ConfigurationManager.AppSettings)
if (key == strKey)return ConfigurationManager.AppSettings[strKey];
return null;
}
4.4 更新appStrings配置节
///<summary>
///在*.exe.config文件中appSettings配置节增加一对键、值对
///</summary>
///<param name="newKey"></param>
///<param name="newValue"></param>
private static void UpdateAppConfig(string newKey, string newValue)
{
bool isModified = false;
foreach (string key in ConfigurationManager.AppSettings)
{
if(key==newKey)
{
isModified = true;
}
}
// Open App.Config of executable
Configuration config =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// You need to remove the old settings object before you can replace it
if (isModified)
{
config.AppSettings.Settings.Remove(newKey);
}
// Add an Application Setting.
config.AppSettings.Settings.Add(newKey,newValue);
// Save the changes in App.config file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");
}
二、对配置信息数据加密
默认情况下,我们需要对App.config文件里的connectionStrings片断进行加密处理,ASP.NET IIS 注册工具 (Aspnet_regiis.exe)可以胜任这个工作,但这个工具只能针对ASP.NET的Web.config文件,难道我们就没有办法了吗?答案当然是否定的。
配置选项
-pdf section webApplicationDirectory对指定物理(非虚拟)目录中的 Web.config 文件的指定配置节进行解密。
-pef section webApplicationDirectory对指定物理(非虚拟)目录中的 Web.config 文件的指定配置节进行加密。
-pdf 和-pef 参数是对指定的物理目录里的Web.config文件进行加密,我们可以先将App.config文件改名为Web.config,通过这两个参数便可以“骗”过系统,让它将指定的配置节进行加密,我们只需要将加密后的文件名改回App.config即可,我们来实验一下:
第一步:先将目录下的App.config改名为Web.config。
第二步:打开SDK命令提示,输入命令:aspnet_regiis -pef "配置节" "目录",以我的项目为例,加密前的config文件内容如下:
1<?xml version="1.0" encoding="utf-8"?>
2<configuration>
3 <configSections>
4 <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
5 </configSections>
6 <dataConfiguration defaultDatabase="Connection String" />
7 <connectionStrings>
8 <add name="Connection String" connectionString="Database=LocomotiveStat;Server=10.167.61.49;User ID=sa;Password=sa;"
9 providerName="System.Data.SqlClient" />
10 </connectionStrings>
11</configuration>
输入命令:aspnet_regiis -pef "connectionStrings" "E:\开发目录",加密后的config文件内容如下:
1<?xml version="1.0" encoding="utf-8"?>
2<configuration>
3 <configSections>
4 <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
5 </configSections>
6 <dataConfiguration defaultDatabase="Connection String" />
7 <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
8 <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
9 xmlns="http://www.w3.org/2001/04/xmlenc#">
10 <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
11 <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
12 <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
13 <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
14 <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
15 <KeyName>Rsa Key</KeyName>
16 </KeyInfo>
17 <CipherData>
18
<CipherValue>g2QFQqbHU1L6WUPYqjADqFAvHcdq/7dqCd1U9GlQFEi/nHDVHjqsWvjNywOZtQQg7Q/yW7g8xlRCo0h2+yYd/tQTNoVMu/RKdJmSjZMnmnwpWq+S2VEWK4U106JQwLCfBR/bAF4DHvG47B9KB0JbRfXBt5V2wJVaAI9u3kzuj50=</CipherValue>
19 </CipherData>
20 </EncryptedKey>
21 </KeyInfo>
22 <CipherData>
23
<CipherValue>blwV/ZW1izFZL80YL5RkcjrIjWkQ0L1gJhgZbxEzzTgOcT24ihrAnv3/rDCG+WIZ7TL5D/rMm7dQwkIsij1Sh3befg6F3+pxcW4oe1w/bovIKuzjs3tokUpBvTTj+fsCs2W/MWUhQaWMKQWkHfS2Ajt6gL6MTYtb3pfQUp0pdHbeRxoqdiAksQ1Zzsi1FtRTi7gTT7hnpF0pJs+W9mxTVDMO/qSZXfXLOEMIs/A5ExcfvR5GjpaPuDeLuSsCN3XtjaiXzaDQ3It7j+r66+L2C0xvEhbT9SsG</CipherValue>
24 </CipherData>
25 </EncryptedData>
26 </connectionStrings>
27</configuration>
由此可见,我们已经完成了任务,现在只需要将Web.config文件名改回App.config即可,在应用程序项目中无需对该文件进行解密操作,.NET框架会自动替我们完成,如果想解密该文件也很简单,在SDK命令提示里输入aspnet_regiis -pdf "配置节" "目录"即可。
DevExpress WinForm应用开发如何利用MVVM设计模式?这里有答案
DevExpress MVVM框架允许您在WinForm应用程序中利用Model-View-ViewModel设计模式,本文将主要为大家介绍什么是MVVM 以及为什么要使用它?
获取工具下载 - DevExpress WinForm v21.1

什么是 MVVM,为什么要使用它?
专为 WPF 开发而设计,Model-View-ViewModel (MVVM)是一种架构设计模式,可将您的应用程序分为三层。
- Model - 定义数据和您的业务逻辑。
- View - 指定UI,包括绑定到ViewModel中的属性和命令的所有可视化元素(按钮、标签、编辑器等)。
- ViewModel - 连接模型和视图。 该层是视图的抽象,它公开用于将数据绑定到 GUI 元素并管理这些数据的公共属性和命令。
下图说明了这些层及其通信方式。

这种分离为您带来了多种好处,例如为开发人员和设计人员提供更独立的开发过程、更轻松的代码测试和更简单的 UI 重新设计。
WinForms应用程序中的MVVM:问题和选项
WinForms平台没有第三方MVVM框架,缺乏敏捷数据绑定或可绑定命令等基本功能。 要遵循MVVM原则,您必须在附加层 - Presenter中手动实现这些功能。 通常,该层包括UserControl及其代码隐藏、自定义View元素的方法、事件处理程序和绑定。
DevExpress MVVM 框架包括对所有必需功能的内置支持,并支持使用 WinForms 进行纯 MVVM 开发,而无需额外的工作负载。 作为一个额外的好处,它可以与您已经在应用程序中使用的 DevExpress WinForms UI 控件很好地集成。
支持的功能和优势列表包括:
- 灵活的数据绑定
- 命令和命令绑定
- 操作和服务
- 一种实现通知和命令的高级方法
- 管理从创建 ViewModel 到注册 DevExpress 服务的所有内容的 MVVM
- 上下文组件
- 简单 (POCO) 类支持
- 与其他DevExpress WinForm控件的丰富互操作性
- 专门为 MVVM 应用程序创建的模板库模板
- 流畅的 API 和数据注释属性支持
- 各种设计时功能
DevExpress WinForm | 下载试用
DevExpress WinForm拥有180+组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!
更多DevExpress线上公开课、中文教程资讯请上中文网获取

今天关于WinForm应用实战开发指南 - 如何完成工作流模块的业务表单开发?和winform工作流控件的讲解已经结束,谢谢您的阅读,如果想了解更多关于.net – 不知道如何使用WinForm应用程序的依赖注入存储库模式工作模式单元、Appium自动化测试实战开发指南、C# 对WinForm应用程序的App.config的使用及加密、DevExpress WinForm应用开发如何利用MVVM设计模式?这里有答案的相关知识,请在本站搜索。
本文标签: