Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform

2023-07-29,,

Expression构建DataTable to Entity 映射委托

 

 1 namespace Echofool.Utility.Common {
 2     using System;
 3     using System.Collections.Generic;
 4     using System.Data;
 5     using System.Linq.Expressions;
 6     using System.Reflection;
 7     using System.Reflection.Emit;
 8
 9     public class DataTableUtility {
10
11         public static IEnumerable<T> Get<T>(DataTable table) where T : new() {
12             if (table == null) {
13                 yield break;
14             }
15             if (table.Rows.Count == 0) {
16                 yield break;
17             }
18             foreach (DataRow row in table.Rows) {
19                 yield return Get<T>(row);
20             }
21         }
22
23         public static T Get<T>(DataRow row) where T : new() {
24             return GenericCache<T>.Factory(row);
25         }
26
27         public class GenericCache<T> where T : new() {
28             static GenericCache() {
29                 //Factory = GetFactoryIL(); 这里写错了                   Factory = GetFactory();
30             }
31             public static readonly Func<DataRow, T> Factory;
32
33             private static Func<DataRow, T> GetFactory() {
34                 var type = typeof(T);
35                 var rowType = typeof(DataRow);
36                 var rowDeclare = Expression.Parameter(rowType, "row");
37                 var instanceDeclare = Expression.Parameter(type, "instance");
38                 var newExpression = Expression.New(type);
39                 var instanceExpression = Expression.Assign(instanceDeclare, newExpression);
40                 var nullEqualExpression = Expression.Equal(rowDeclare, Expression.Constant(null));
41                 var containsMethod = typeof(DataColumnCollection).GetMethod("Contains");
42                 var indexerMethod = rowType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public, null,
43                                                       new[] { typeof(string) },
44                                                       new[] { new ParameterModifier(1) });
45                 var setExpressions = new List<Expression>();
46                 var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
47                 var columns = Expression.Property(Expression.Property(rowDeclare, "Table"), "Columns");
48                 foreach (var propertyInfo in properties) {
49                     if (propertyInfo.CanWrite) {
50                         var propertyName = Expression.Constant(propertyInfo.Name, typeof(string));
51                         var checkIfContainsColumn =
52                             Expression.Call(columns, containsMethod, propertyName);
53                         var propertyExpression = Expression.Property(instanceDeclare, propertyInfo);
54                         var value = Expression.Call(rowDeclare, indexerMethod, propertyName);
55                         var proertyAssign = Expression.Assign(propertyExpression, Expression.Convert(value, propertyInfo.PropertyType));
56                         setExpressions.Add(Expression.IfThen(checkIfContainsColumn, proertyAssign));
57                     }
58                 }
59                 var checkIfRowIsNull = Expression.IfThenElse(nullEqualExpression, Expression.Empty(), Expression.Block(setExpressions));
60                 var body = Expression.Block(new[] { instanceDeclare }, newExpression, instanceExpression, checkIfRowIsNull, instanceDeclare);
61                 return Expression.Lambda<Func<DataRow, T>>(body, rowDeclare).Compile();
62             }
63         }
64
65         public static T GetByReflection<T>(DataRow dr) where T : new() {
66             var t = new T();
67             if (dr != null) {
68                 foreach (var p in typeof(T).GetProperties()) {
69                     if (!dr.Table.Columns.Contains(p.Name)) {
70                         continue;
71                     }
72                     var obj = dr[p.Name];
73                     var set = p.GetSetMethod();
74                     if (set == null) {
75                         continue;
76                     }
77                     p.SetValue(t, obj, null);
78                 }
79             }
80             return t;
81         }
82     }
83 }

通过Expression动态构建DataTable映射到实体类,在三层架构中,如果使用的数据层是使用Ado.Net技术,那么加上这个DataTable to Entity的工具类,将为你减少很多代码量。

主要目的是解决DataTable到Entity的映射关系。

 1         public class MyClass {
 2             public MyClass() { }
 3
 4             public MyClass(DataRow row) {
 5                 if (row != null) {
 6                     if (row.Table.Columns.Contains("Name")) {
 7                         this.Name = (string)row["Name"];
 8                     }
 9                     if (row.Table.Columns.Contains("Age")) {
10                         this.Age = (int)row["Age"];
11                     }
12                 }
13             }
14
15             public string Name { get; set; }
16             public int Age { get; set; }
17
18         }

如上定义的实体类MyClass,有一个string类型的Name属性和一个int类型的Age属性。

如果自定义构造函数是可以很方便的从DataRow对象中获取数据填充实体类,但如果涉及的实体类太多,而且如果想通过定义特性标记 来实现一些字段特殊处理,构造函数的方式,需要你写太多的代码,而且很多都是重复的逻辑。

现在使用DataTableUtility.Get<MyClass>.Get(row);就能很方便的获取一个实体类。

现在使用DataTableUtility.Get<MyClass>.Get(table);就能很方便的获取一个实体类集合。

sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。

 

项目当中如果设计到金额类型的数据,你是否有考虑过为什么不能用float类型。

这里举个例子:

1
2
3
4
5
6
7
8
9
10

DECLARE @price1 FLOAT;
SET @price1 = 1;
SET @price1 = ( @price1 * 7.1 ) / 7 - @price1 * 0.1
SELECT  @price1;
 
 
DECLARE @price2 DECIMAL;
SET @price2 = 1;
SET @price2 = ( @price2 * 7.1 ) / 7 - @price2 * 0.1
SELECT  @price2;

  执行看看结果如何:

0.914285714285714

1

这里做个记录,开发中遇到的小问题。

sql server 多行数据合并成一列

 

首先是源数据:

select (CONVERT(varchar(100),cip.CheckIn_StartTime, 23)+' - '+CONVERT(varchar(100),cip.CheckIn_EndTime, 23)+' '+CONVERT(varchar(100),cip.Rental_Price)) as content from CheckInPeriod cip 

然后我们加上合并语句:

select Stuff((select ',' +Convert(varchar(255),content) from (
select (CONVERT(varchar(100),cip.CheckIn_StartTime, 23)+' - '+CONVERT(varchar(100),cip.CheckIn_EndTime, 23)+' '+CONVERT(varchar(100),cip.Rental_Price)) as content from CheckInPeriod cip
) tba
for XML path('')),1,1,'') as content

结果就是这样的:

可以自定义各种符号。

C# 字符串大写转小写,小写转大写,数字保留,其他除外

 

又是一道面试题,我只想到两种方式:

第一种:循环字符串,判断每个字符串的类型,再根据类型对该字符进行操作(转大写、转小写、不变或舍弃)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

static void Main(string[] args)
{
    //大写转小写,小写转大写,数字保留,其他除外
    string str = "Aa Bb 123!@#";     //测试字符串
    string newStr = string.Empty;    //用于存放新字符串
     
    //循环字符串
    foreach (char item in str)
    {
        if (item >= 'a' && item <= 'z')
        {
            //小写字母转大写
            newStr += item.ToString().ToUpper();
        }
        else if (item >= 'A' && item <= 'Z')
        {
            //大写字母转小写
            newStr += item.ToString().ToLower();
        }
        else if (item >= '0' && item <= '9')
        {
            //数字不变
            newStr += item.ToString();
        }
    }
    //打印
    System.Console.WriteLine(newStr);
    System.Console.ReadLine();
}

第二种:将字符串转为byte[],循环byte[],使用ASCII码进行判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

static void Main(string[] args)
{
    //大写转小写,小写转大写,数字保留,其他除外
    string str = "Aa Bb 123!@#";     //测试字符串
    string newStr = string.Empty;    //用于存放新字符串
 
    //字符串-->byte[]
    ASCIIEncoding ascii = new ASCIIEncoding();
    byte[] bytes = ascii.GetBytes(str);
 
    //循环byte[]
    foreach (byte item in bytes)
    {
        //临时存放
        byte[] temp = new byte[] { item };
 
        if (item >= 97 && item <= 122)
        {
            //小写字母转大写
            newStr += ascii.GetString(temp).ToUpper();
        }
        else if (item >= 65 && item <= 90)
        {
            //大写字母转小写
            newStr += ascii.GetString(temp).ToLower();
        }
        else if (item >= 48 && item <= 57)
        {
            //数字不变
            newStr += ascii.GetString(temp);
        }
    }
    //打印
    System.Console.WriteLine(newStr);
    System.Console.ReadLine();
}

备注:数字,字母的ASCII码对照表

1
2
3
4
5

/*
0~9数字对应十进制48-57
a~z字母对应的十进制97-122十六进制61-7A
A~Z字母对应的十进制65-90十六进制41-5A
*/

结果打印:

从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法

 

一,制作U盘启动盘

  随着个人电脑的“飞入寻常百姓家”,喜欢DIY电脑的发烧友们也越来越多。

  安装系统是DIY最基本的要求,很容易做到;

  那么如果要求用U盘装系统呢,你可能会说简单,直接下载个老毛桃或是大白菜一类的软件一键就搞定了;

  那么如果要求用系统自带的命令行工具制作U盘启动安装盘呢?

工具/原料:

  U盘一个(4G可能不够用,最好8G
  系统iso镜像一个(这里用Win10企业版)

方法/步骤:

  1,把要制作成U盘启动安装盘的U盘,插入到电脑的USB接口中,确保资源管理器已经正确识别U盘。下图中是小编的8G的U盘,实际有效容量是7.60G。

  2,右键左下角开始按钮,选择“命令提示符(管理员)”。

  3,在命令行中输入“diskpart”(不包括双引号,下同)后按回车键,此命令是Windows系统自带的硬盘分区工具。

  4,在命令行中输入“list disk”后按回车键,此命令用于显示电脑上所有的硬盘(注意,diskpart会把U盘也看成硬盘),从“大小”一栏中一下就能看到U盘被看做了“磁盘 1”,这一步非常重要,因为后面会格式化,所以一定要仔细确定哪个是U盘并记住U盘的编号。

  5,在命令行中输入“select disk 1”后按回车键,此命令用于选择接下来要操作的磁盘,这里的“1”就是小编的U盘编号(从上一步所得)。

  6,在命令行中输入“clean”后按回车键,此命令用于清除U盘上的所有数据,所以在执行此步骤之前,如果U盘中有重要数据,务必备份,否则会被清除无法恢复。

  7,在命令行中输入“create part pri”后按回车键,此命令是“create partition primary”的简写形式,作用是在U盘上创建主分区。

  8,在命令行中输入“select part 1”后按回车键,此命令是“select partition 1”的简写形式,作用是选择分区1,也就是上一步创建的主分区。

  9,在命令行中输入“format fs=fat32 quick”后按回车键,此命令用于快速格式化主分区为fat32文件系统格式。

  10,在命令行中输入“active”后按回车键,此命令用于把当前分区标志为“活动”。

  11,在命令行中输入“exit”后按回车键,此命令用于退出diskpart分区工具。

整个过程截图如下:

OK了,现在U盘已经变成可启动U盘了。你只需要把下载好的Win10系统的iso文件解压到U盘中即可。是的,就是解压iso文件,任何解压软件都可以,关键是解压到U盘的根目录中。

接下来就是设置从U盘启动了,启动之后就自动开始安装Win10系统,过程和使用光盘一致。祝你DIY愉快!

注意事项:纵观整个过程,最重要的就是创建一个活动主分区。

参考链接:https://jingyan.baidu.com/article/8cdccae9577e0e315413cd87.html

二,下载 cn_windows_10_enterprise_2015_ltsb_x64_dvd_6848425.iso

可以去windows 官网下载Windows 10,然而我是在这里下载的 https://msdn.itellyou.cn/ ,打开页面,左侧菜单找到“操作系统”,点击展开“Windows 10”,右边栏选择“中文-简体”,找到“Windows 10 Enterprise 2015 LTSB (x64) - DVD (Chinese-Simplified)”点击详细信息。

直接用迅雷或者其他下载工具下载:

ed2k://|file|cn_windows_10_enterprise_2015_ltsb_x64_dvd_6848425.iso|3907538944|38E47AB92B6D97DF2BE602BBC9969D34|/

下载到本地是 cn_windows_10_enterprise_x64_dvd_6846957.iso 就是简体中文的Windows 10 企业版压缩包。

解压缩,将里面的文件全部拷贝到前面制作好的U盘根目录下。

三,下载Intel Raid模式驱动(固态硬盘驱动) 如果电脑没有装固态硬盘则跳过此步骤

  因为我的笔记本是 “512G固态硬盘+1T普通硬盘” ,针对固态硬盘需要Intel Raid模式驱动。

最近使用联想R720笔记本用户反应在重装系统的时候无法识别硬盘的现象,是怎么回事呢?出现这样的问题是由于R720出厂系统的BIOS内,SATA Controller Mode默认设置的是为Intel RST Premium模式,该模式会将硬盘组成磁盘阵列的模式(Raid模式),而原版的Window 10安装镜像默认没有Raid模式的驱动导致的,当然我们可以按下面方法进行修复。

解决方法:
  下载Intel Raid模式驱动,将驱动安装包解压缩后将整个文件夹完整的放到到系统安装U盘的根目录下,然后在安装系统选择硬盘时,加载此驱动。(该驱动分为32位和64位,分别对应32位系统和64位系统吗,下载地址:http://pan.baidu.com/s/1o8QghFs)。

  下载后是 f6flpy.rar ,解压缩后包含两个 f6flpy-x64,f6flpy-x86,根据你要装系统的电脑选择64位(f6flpy-x64),或者32位(f6flpy-x86),拷贝到上一步制作U盘的根目录下。

参考链接:https://m.baidu.com/from=1012852s/bd_page_type=1/ssid=c43dd0dcd7d0c6e4c8cb990a/uid=0/pu=usm%401%2Csz%40224_220%2Cta%40iphone___3_537/baiduid=7D3A0142A57B1B1E187C45C49732C21B/w=0_10_/t=iphone/l=3/tc?ref=www_iphone&lid=8408291642588093132&order=3&fm=alop&tj=www_normal_3_0_10_title&vit=osres&m=8&srd=1&cltj=cloud_title&asres=1&title=%E8%81%94%E6%83%B3R720%E9%87%8D%E8%A3%85Winddows10%E6%97%A0%E6%B3%95%E8%AF%86%E5%88%AB%E5%9B%BA%E6%80%81%E7%A1%AC%E7%9B%98%E5%92%8B%E5%8A%9E--%E7%B3%BB%E7%BB%9F%E4%B9%8B%E5%AE%B6&dict=32&wd=&eqid=74b040b32c595c00100000035b012bc5&w_qd=IlPT2AEptyoA_ykxvPQbu4BsrNGJAeInrU5XlQzTsvMtNfX84E5IpI7H7fUOt_J5&tcplug=1&sec=29912&di=22388f78e991c45a&bdenc=1&nsrc=IlPT2AEptyoA_yixCFOxXnANedT62v3IEQGG_zZRBjW5mlmuefrbGRhoZyOqAp7FJkfjvG3EhgoDlj4yQWUmzBAxr_lktGk6kzm9u_&sfOpen=1

四,从U盘启动,装Windows 10 企业版系统

  1,将要装系统的电脑C盘(包含桌面)上的个人文件及数据备份到其他盘。然后关机。插入U盘(前面制作好启动分区的U盘,里面包含系统全部安装文件)。

  2,开机,然后连续按开机设置键(联想是F12),进入启动菜单(Boot Menu),找到USB启动项。按回车,重启及进入U盘开始安装系统。

  3,到了选择“您想将Windows安装在哪里?”的时候要小心了。看准主分区(原C盘),其它磁盘分区不要动,一面数据丢失。

因为我的C盘是在固态硬盘中,所以到这里是看不见的。于是就用到了上面第三步中提到的Intel Raid模式驱动。点击“加载驱动程序”,然后“浏览”,找到存放Raid驱动的文件夹,默认文件名为“f6flpy-x86”或“f6flpy-x64”,选择该文件,然后确定。

  耐心等待检测到Raid模式驱动程序,点击下一步后,出现读取条开始加载此驱动。(如果提示报错建议重新加载该驱动多试几次,并且驱动文件存放的路径最好为全英文路径)。

  在加载成功后会跳回之前选择硬盘的界面,此时已经可以正常显示出机器内的固态硬盘,开始正常安装即可!

好了,后面就是按照步骤操作就行了,没啥可说的了。祝你一切顺利!

五,检查更新系统驱动

  重装系统后,进入新系统桌面。去官网(我用的联想笔记本,地址是 http://support.lenovo.com.cn/lenovo/wsi/Modules/NewDrive.aspx )点击“立即安装驱动”下载联想驱动管家。或者驱动精灵等。安装好后检查更新一遍驱动就好了。

六,Win10企业版永久激活

  win10企业版永久激活方法?win10企业版是针对企业用户推出的版本,随着win10系统的不断完善,现在越来越多的人选择升级win10,升级完系统就需要激活它。那么今天就为大家分享一下怎么永久激活win10企业版。

  1、右键点击桌面左下角"windows"图标,点击打开“命令提示符”。

  2、复制命令:slmgr.vbs /upk,按回车确定,弹出窗口显示“成功地卸载了产品密钥”。

  3、复制命令:slmgr /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43,按回车确定,弹出窗口显示“成功的安装了产品密钥NPPR9-FWDCX-D2C8J-H872K-2YT43”。

  4、复制命令:slmgr /skms zh.us.to,按回车确定,弹出窗口显示“密钥管理服务计算机名成功的设置为zh.us.to”。

  5、复制命令:slmgr /ato,按回车确定,弹出框口提示“成功激活产品”。

以上就是如何使用win10激活密钥永久激活win10企业版的方法。

参考链接:http://www.xitongzhijia.net/xtjc/20180125/118672.html

—— 致敬周末两天装系统踩过的坑……

纯CSS打造淘宝导航菜单栏

 

店铺装修-PC端-基础页-首页-装修页面:编辑“菜单”模块-显示设置,粘贴如下CSS:

/* 导航条背景色*/
.skin-box-bd .menu-list{background: none repeat scroll 0 0 #3F7FCE;}
/*首页/店铺动态背景色*/
.skin-box-bd .menu-list .link{
    background: none repeat scroll 0 0 #3F7FCE;
    color: #C2D5ED;
    font-family: 微软雅黑,黑体;
    font-weight: bold;
    font-size: small;}
/*首页/店铺动态右边线*/
.skin-box-bd .menu-list .menu{
    border-width: 0 1px 0 0;
    border-color: #3871B7;
    border-style: solid;
    background: #3F7FCE;
    font-size: 14px;}
.skin-box-bd .menu-list .menu-hover .link{background: none repeat scroll 0 0 #3487ed;}

/*首页/店铺动态文字颜色*/
.skin-box-bd .menu-list .menu .link .title{color:#fff}
.skin-box-bd .menu-list .menu-selected .link .title{background: none repeat scroll 0 0 #3F7FCE;}
.skin-box-bd .menu-list .menu-hover .link .title{background: none repeat scroll 0 0 #3487ed;}

/*下拉菜单图标*/
.skin-box-bd .menu-list .menu .link .popup-icon{
    height: 12px;
    width: 12px;
    background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) -14px -179px no-repeat;
}
.skin-box-bd .menu-list .menu-hover .link .popup-icon{
    height: 12px;
    width: 12px;
    background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) -14px -199px no-repeat;
}
/*二级菜单*/
.menu-popup-cats .sub-cat{background: none repeat scroll 0 0 #2c5990;}
.menu-popup-cats .sub-cat-hover{background: none repeat scroll 0 0 #3487ed;color: #FFF;}
.menu-popup-cats li.sub-cat-hover::before{content: '%3e';}

/*所有分类背景色*/
.skin-box-bd .all-cats .link{background: none repeat scroll 0 0 #ff4400;padding: 0 15px;}
/*所有分类文字颜色*/
.skin-box-bd .all-cats .title{
    color: #f5f5f5;
    font-family: 微软雅黑,黑体;
    font-weight: bold;
    font-size: small;
}

/*所有分类-下拉菜单图标*/
.skin-box-bd .all-cats .link .popup-icon {
    height: 12px;
    width: 12px;
    background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) 0 -220px no-repeat;
}
.skin-box-bd .all-cats-hover .link .popup-icon {
    height: 12px;
    width: 12px;
    background: url(//gdp.alicdn.com/tps/i1/T18WsRFcpdXXXPXsT8-51-381.gif) 0 -240px no-repeat;
}
/*所有分类-二级菜单*/
.skin-box-bd .popup-content .cats-tree .fst-cat{background: none repeat scroll 0 0 #2c5990;}
.skin-box-bd .popup-content .cats-tree .cat-hd-hover{background: none repeat scroll 0 0 #3487ed;color: #FFF;}
/*所有分类-三级菜单*/
.skin-box-bd .popup-content .cats-tree .fst-cat .snd-pop .snd-cat-hd a{ background: none repeat scroll 0 0 #2c5990;color: #C2D5ED; }
.skin-box-bd .popup-content .cats-tree .fst-cat .snd-pop .snd-cat-hd-hover a{background: none repeat scroll 0 0 #3487ed;color: #FFF;}

自定义导航示例:https://hotshop.bbs.taobao.com/detail.html?postId=7000589

进入CSS导航在线生成工具页面(http://taobaokaidian.com/tool/dhcss/ 如果不能点击打开,请复制网址到时浏览器中打开),

想了解更多样式,可以来这里学习css : http://www.w3cschool.cn/css_intro.html

C# Winform开发以及控件开发的需要注意的,被人问怕了,都是基础常识

 

我是搞控件开发的,经常被人问,所以把一些问题记录了下来!如果有人再问,直接把地址丢给他看。

一、 经常会有人抱怨Winform界面闪烁,下面有几个方法可以尽可能的避免出现闪烁

1.控件的使用尽量以纯色为主,尽量不使用背景图,或者把大图改成小图,或者图片不缩放绘制,或者直接用不透明的纯色背景色(Winform控件透明是伪透明,是通过截取父容器背景来实现的,所以效率比较低,而且有时候会有延迟。而且多个透明控件叠加的时候不能分层显示出各个控件的透明效果)

2.自定义控件中使用双缓冲。

3.窗体边框最好不要设置为None,保留窗体最大化最小化动画,可以避免最小化恢复时候的界面闪烁。可能会有人说我的窗体是自定义美化的,边框为None了。其实可以通过拦截消息重绘非客户区,实现边框不为None的时候重绘整个窗体的。 网上也有很多教程

二、自定义控件时候需要注意的

1.控件重绘的时候尽可能的处理e.ClipRectangle,减少不必要的绘图操作,标准重绘都应该在Paint事件里处理,用事件里的e.Graphics

而不是在随便个地方就用CreateGraphics()来绘制,需要刷新的时候调用 Invalidate() 如果能计算重绘区域最好

2.使用双缓冲,在构造函数里加入这两行代码 减少闪烁

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);

或者

DoubleBuffered = true;


3.如果你开发dll组件给别人用,记得项目属性里,生成,选择 XML文档文件,生成///<summary> 代码注释。到时候把dll给别人用的时候也把Xml带上,放到和dll同一个目录,这样别人开发的时候就有注释提示了

三、其他开发问题

1.多线程操作控件请使用控件的Invoke或者BeginInvoke调用

不要总想着其他线程中直接操作控件,会出现很多奇葩问题的。

Control.CheckForIllegalCrossThreadCalls       这个属性就是掩耳盗铃,就和  SetProcessWorkingSetSize(将内存强制压到虚拟内存里,给硬盘增加压力) 用来释放内存一样。当初不知道谁传出来的,误导一群人!

正常的多线程操作控件是

this.Invoke(new MethodInvoker(() => {
  //UI操作代码
}));

或者用 async 语法 异步编程

不过还有人用很古老的写法,定义委托,判断 InvokeRequired在调用Invoke,虽然也可以,但是浪费时间。

还有 Application.DoEvents();  也是个远古代码,能不用就不要用

使用线程的时候记得设置线程的 IsBackground=true; 程序关闭之后,线程能自动退出

2. 颜色System.Drawing.Color 这个结构体  是可以支持设置透明度的。可以3个或者4个值,Color.FromArgb(),4个值的时候是 Alpha,Red,Green,Blue. 第一个就是透明度的参数 0-255

3.如果你想把窗体最大化的时候全屏,遮住任务栏,请把窗体边框设置为None

4.控件布局的时候活用DockAnchor,这两个属性是互斥的

5.单行的TextBox的高度受字体影响,不能单独改。如果想美化边框效果,请把TextBox的边框隐藏了,放到Panel里,Panel在加个边框背景美化。

6.Label换行只要有\r\n就会换行的,如果要自动换行,先把AutoSize改成false,设置好宽度。字符超过宽度就会换行的。

7.System.Windows.Forms.Timer 这个是执行在主线程的,本质是控件消息循环里的一个定时消息,不要用来做耗时的操作。耗时操作请用 System.Threading.Timer和 System.Timers.Timer

8.Winform 对DPI支持的不完善,虽然.NET Framework 4.6 中有EnableWindowsFormsHighDpiAutoResizing。但是你必须所有控件用原生控件。

如果你用的不是.Net.4.6 而且使用了第三方控件,为了不影响布局,建议把里面的字体单位都改成像素,容器控件包括窗体的AutoScaleMode属性改成None。这样至少界面布局基本正常,高DPI里只是模糊了些

9.使用非托管资源最好显式调用Dispose释放资源,比如图片,文件读取等等。

this.BackgroundImage = global::WinFormsTest.Properties.Resources.bt;

Properties.Resources这个对象的图片属性,每次访问会创建一个图片副本,如果多个控件使用同一张图片,建议手动写代码设置,先设置到一个静态字段里,再引用这个图片字段。

10. try 不要乱用,能解决问题的能不加try的就不要加try,太多try容易导致异常不好定位。一般对于不确定是否异常的才需要加try,比如文件读取,网络连接等等,另外一种是一般开发底层框架的可以确定异常类型,可以配合throw new Exception,用来提示开发者调用出错的信息。另外异常可以全局捕获在 Application.Run加try和ThreadException事件记录日志。

之前看到有些人写一大堆try,程序运行靠try维持,简单的错误没有判断过滤掉,靠try来忽略。导致整个程序卡的一比!

四、一些VS快捷键

1.代码+Tab+tab   VS代码快速生成补全,比如 if 再按两下Tab就可以生成if(){}。 mb + Tab+tab= MessageBox.Show("Test");  try、switch、事件绑定+=等等。很多代码都可以用这种方式快速生成。

2. F12 转定义,Ctrl+R+R 重命名, Ctrl + F 除了查找之外,还可以做正则表达式的简单验证,因为匹配结果可以染色。

其他问题自己先去百度吧!

最后问一下:Winform还有多少人用,很多人都转WPF了吧?另外.net的跨平台UI有没有意义?

Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform的相关教程结束。

《Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform.doc》

下载本文的Word格式文档,以方便收藏与打印。