C.Net串口工具源码 串口调试工具 支持16进制发送 可以定时自动发送

软件功能:


使用C#实现PC串口通讯

支持定时发送

支持16进制(hex) ASCII UTF-8 Unicode 四种编码格式

支持配置文件的保存和读取

可以可以显示发送历史

可以统计总的发送字节数和接受字节数

软件界面:


Screen Shot 2018-03-17 at 17.47.04 PM.png


C#源码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.IO;
using System.Xml.Serialization;

namespace 串口调试工具
{
    public partial class Form1 : Form
    {
        private SerialPort sp = new SerialPort();//链接对象
        Config config = new Config();//配置文件

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //获取串口列表
            string[] comList = SerialPort.GetPortNames();
            if (comList.Length == 0)
            {
                MessageBox.Show("无可用串口");
                return;
            }
            foreach (var com in comList)
            {
                cmbComList.Items.Add(com);
            }


            //添加波特率
            int[] baudRate = { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 43000, 56000, 57600, 115200 };
            foreach (var br in baudRate)
            {
                cmbBautRade.Items.Add(br);
            }

            //添加数据位
            int[] dataBits = { 8, 7, 6, 5 };
            foreach (var db in dataBits)
            {
                cmbDataBits.Items.Add(db);
            }

            //添加停止位
            int[] stopBits = { 1, 2, 3 };
            foreach (var sb in stopBits)
            {
                cmbStopBits.Items.Add(sb);
            }

            //添加检验方式
            string[] parity = { "None", "Even", "Mark", "Odd", "Space" };
            foreach (var p in parity)
            {
                cmbParity.Items.Add(p);
            }

            //添加常用编码
            string[] encode = { "ASCII","UTF-8","Unicode","Hex"};
            foreach (var en in encode)
            {
                cmbEncodeSend.Items.Add(en);
                cmbEncodeRec.Items.Add(en);
            }

            //加载配置文件
            LoadConfig();
        }

        private void LoadConfig()
        {
            //把配置信息赋值给控件默认值
            cmbComList.SelectedItem = config.PortName;
            if (cmbComList.SelectedIndex == -1) cmbComList.SelectedIndex = 0;
            cmbBautRade.SelectedItem = config.BautRade;
            cmbDataBits.SelectedItem = config.DataBits;
            cmbStopBits.SelectedItem = config.StopBits;
            cmbParity.SelectedItem = config.Parity;
            cmbEncodeRec.SelectedItem = config.EncodeRec;
            cmbEncodeSend.SelectedItem = config.EncodeSend;

            //激活打开按钮
            this.btnOpen.Enabled = true;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (((Button)sender).Text == "打开串口")
            {
                //赋值给串口
                sp.PortName = cmbComList.SelectedItem.ToString();
                sp.Parity=(Parity)Enum.Parse(typeof(Parity),cmbParity.SelectedItem.ToString());
                sp.BaudRate = Convert.ToInt32(cmbBautRade.SelectedItem.ToString());
                sp.StopBits = (StopBits)Convert.ToInt32(cmbStopBits.SelectedItem.ToString());
                sp.DataBits = Convert.ToInt32(cmbDataBits.SelectedItem.ToString());

                try
                {
                    sp.Open();

                    //修改控件状态
                    this.btnOpen.Text = "关闭串口";
                    foreach (Control ctr in groupBox1.Controls)
                    {
                        //把下拉框全部禁用
                        ctr.Enabled = false;
                    }

                    //开启新线程,监听收取内容
                    Thread thread = new Thread(receive);
                    thread.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else
            {
                if (this.btnAutoSend.Text == "停止发送")
                {
                    MessageBox.Show("当前定时发送中,请先停止定时发送任务.");
                    return;
                } 
                sp.Close();

                //修改控件状态
                this.btnOpen.Text = "打开串口";
                foreach (Control ctr in this.groupBox1.Controls)
                {
                    ctr.Enabled = true;
                }
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //窗体关闭时关闭端口
            sp.Close();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            Send();
        }

        private void btnAutoSend_Click(object sender, EventArgs e)
        {
            if (this.btnAutoSend.Text == "定时发送")
            {
                //根据打开按钮状态初步检查端口是否已经打开
                if (this.btnOpen.Text == "打开串口") return;

                System.Text.RegularExpressions.Regex reg1 = new System.Text.RegularExpressions.Regex(@"^[0-9]\d*$");
                if (reg1.IsMatch(txtTime.Text.ToString()))
                {
                    //激活Timer定时器
                    this.timer1.Interval = Convert.ToInt32(txtTime.Text.ToString());
                    this.timer1.Start();

                    //修改控件状态
                    this.btnAutoSend.Text = "停止发送";
                    this.btnSend.Enabled = false;

                }
                else
                {
                    MessageBox.Show("发送间隔应为正整数");
                    txtTime.Text = "1000";
                }
            }
            else
            {
                this.btnAutoSend.Text = "定时发送";
                this.btnSend.Enabled = true;
                this.timer1.Stop();
            }
        }

        private void Send()
        {
            if (sp.IsOpen)
            {
                //获取字节
                byte[] buffer = Encode();
                if (buffer.Length == 0) return;

                try
                {
                    sp.Write(buffer, 0, buffer.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

                //添加发送历史
                this.txtHistory.AppendText(string.Format("[{0}] {1} \r\n", DateTime.Now.ToString("HH:mm:ss.ff"), txtSend.Text));
                //统计发送字节
                this.labSendCount.Text = (Convert.ToInt32(labSendCount.Text) + buffer.Length).ToString();
            }
            else
            {
                this.timer1.Stop();
                MessageBox.Show("串口尚未打开");
                this.btnAutoSend.Text = "定时发送";
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //定时发送
            Send();
        }

        //字节反编码
        private byte[] Encode()
        {
            byte[] buffer = null;

            switch (this.cmbEncodeSend.SelectedItem.ToString())
            {
                case "Unicode":
                    buffer = Encoding.Unicode.GetBytes(txtSend.Text); 
                    break;
                case "UTF-8":
                    buffer = Encoding.UTF8.GetBytes(txtSend.Text);
                    break;
                case "ASCII":
                    buffer = Encoding.ASCII.GetBytes(txtSend.Text);
                    break;
                case "Hex":
                    buffer = strToToHexByte(txtSend.Text);
                    break;
            }

            return buffer;
        }
        //编码
        private string UnEncode(byte[] buffer)
        {
            string str = string.Empty;

            switch (this.cmbEncodeSend.SelectedItem.ToString())
            {
                case "Unicode":
                    str = new UnicodeEncoding().GetString(buffer);
                    break;
                case "UTF-8":
                    str = new UTF8Encoding().GetString(buffer);
                    break;
                case "ASCII":
                    str = new ASCIIEncoding().GetString(buffer);
                    break;
                case "Hex":
                    str = byteToHexStr(buffer);
                    break;
            }

            return str;
        }
        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }
        /// <summary>
        /// 字符串转16进制字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private static byte[] strToToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        private void receive()
        {
            //接收信息 先判断是否为打开状态
            while (sp.IsOpen)
            {
                if (sp.BytesToRead == 0) continue;

                //准备接收
                byte[] buffer = new byte[sp.BytesToRead];
                try
                {
                    //接受动作
                    sp.Read(buffer, 0, buffer.Length);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

                //更新UI信息
                this.Invoke((Action)delegate
                {
                    this.txtRec.AppendText(UnEncode(buffer));
                    //是否自动换行
                    if(cbLine.Checked)
                        this.txtRec.AppendText("\r\n");

                    //接收统计信息
                    this.labRecCount.Text = (Convert.ToInt32(this.labRecCount.Text) + buffer.Length).ToString();
                });
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //清空发送历史
            this.txtHistory.Clear();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //清空接收
            this.txtRec.Clear();
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            //读取xml文件 序列化对象
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "XML(*.xml)|";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                string filePath = ofd.FileName;
                if (File.Exists(filePath))
                {
                    try
                    {
                        var mySerializer = new XmlSerializer(typeof(Config));
                        using (var sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read)))
                        {
                            config = (Config)mySerializer.Deserialize(sr);
                        }
                        LoadConfig();
                    }
                    catch (Exception ee)
                    {
                        MessageBox.Show(ee.Message);
                    }
                }
                else
                {
                    MessageBox.Show("文件不存在");
                }
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {

            FolderBrowserDialog fbd = new FolderBrowserDialog();            
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                //给对象赋值并序列化保存
                config.PortName = cmbComList.SelectedItem.ToString();
                config.Parity = cmbParity.SelectedItem.ToString();
                config.BautRade = Convert.ToInt32(cmbBautRade.SelectedItem.ToString());
                config.StopBits = Convert.ToInt32(cmbStopBits.SelectedItem.ToString());
                config.DataBits = Convert.ToInt32(cmbDataBits.SelectedItem.ToString());

                XmlSerializer xmlFormat=new XmlSerializer(typeof(Config));
                string filePath = fbd.SelectedPath + "\\PortConfig.xml";
                using (Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    xmlFormat.Serialize(stream, config);
                }
                MessageBox.Show("成功保存到路径:"+filePath);
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.chengchenxu.com");  
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 串口调试工具
{
    [Serializable]
    public class Config
    {
        public string PortName { get; set; }
        public int BautRade { get; set; }
        public int DataBits { get; set; }
        public string Parity { get; set; }
        public string EncodeSend { get; set; }
        public string EncodeRec { get; set; }
        public int StopBits { get; set; }
        public Config()
        {
            //默认值
            BautRade = 9600;
            DataBits = 8;
            Parity = "None";
            EncodeSend = "ASCII";
            EncodeRec = "ASCII";
            StopBits = 1;
        }
        
    }
}


软件下载:

串口调试工具.rar


源码工程文件:

串口调试工具.rar


虚拟端口软件下载:

VirtualSerialPortDriver.rar


未实现的功能:

16进制校验功能,即发送16进制格式的时候检查输入值是否为正确的16进制数字

接受文件的完整性校验功能,有时候一条信息会分两次接受完整


利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理

该类在MVC中可以方便管理配置信息,可以直接把Model储存进数据库或者从数据库去除数据转为Model.

1 何为配置项目?

比如网站的名称,页脚信息,meta中的KeyWord信息等,如果不想硬编码到网页里,就需要使用配置文件进行储存,通常都是储存到数据库中.使用的时候读取出来,也方便修改.

2 MVC中对于数据的编辑一般是Model建模,然后View调用强类型,使用诸如@Html.TextBoxFor(m=>m.Name)之类的方式,取值时可以直接取到Model,不用再根据Request.From来一个一个的去赋值.

3 MVC的特性提供了强大的数据自检能力,如果Model中属性为Int类型,那么输入的时候如果不是数字则会直接提示类型错误.该特性支持正则表达式,可以说不用写一句js代码就可以完成数据的服务器端和客户端双重验证,十分强大.

4 本类只有两个方法,一个Load 一个Save,顾名思义,一个读取一个储存.参数都采用了泛型.你可以创建一个ConfigWebSIteModel基本设置类,

然后再创建一个ConfigSeo类,来分别管理不同的配置项目,可以一并储存到一个数据表中.

        T Load<T>();
        void Save<T>(T t);

不用的类中的属性不可以重复,否则会覆盖,比如ConfigWebSiteModel中有个ConfigWebSiteModel.Name 那么 ConfigSeo中就不能在出现Name属性,否则会覆盖掉,出错.


核心代码:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Text;
using ChengChenXu.Blog.Models;
using System.Reflection;
using System.Data.SqlClient;

namespace ChengChenXu.Blog.DAL.SqlServer
{
    public class ConfigModelDAL:IConfigModelDAL
    {
        private readonly string tableName = "blog_Config";//表名
        private readonly string columnKey = "c_Key";//key列名
        private readonly string columnValue = "c_Value";//Value列名
        private readonly string columnType = "c_Type";//Type列名
       


        /// <summary>
        /// 加载
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Load<T>()
        {
            //通过sqlhelper获取datatable
            string sql = "select * from " + tableName;
            DataTable dt = SqlHelper.ExecuteDataTable(sql);

            //不存在记录
            if (dt.Rows.Count == 0) return default(T);

            //表行转换成列 ,临时表
            DataTable temp = new DataTable();
            foreach (DataRow dr in dt.Rows)
            {
                //添加一列,设置列的数据类型
                DataColumn dc = new DataColumn();
                dc.ColumnName = dr[columnKey].ToString();
                //根据字符串设置数据类型
                dc.DataType = System.Type.GetType(dr[columnType].ToString());
                temp.Columns.Add(dc);

                //如果时第一列,添加一行
                int index = temp.Columns.Count - 1;
                if (temp.Rows.Count == 0) temp.Rows.Add();

                //如果不是第一例,则行必定已经存在,直接赋值
                temp.Rows[0][index] = dr[columnValue];
            }

            if (temp.Columns.Count == 0) return default(T);

            //把临时表转换成Model并返回
            return temp.Rows[0].ToModel<T>();
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public void Save<T>(T t)
        {
            //利用反射获取对象所有属性
            string attributeName = String.Empty;
            PropertyInfo[] propertys = t.GetType().GetProperties();

            //获取数据库配置表放到内存中,对比数据是否已经存在
            DataTable dt = new DataTable();
            if (propertys.Length > 0)
            {
                dt = SqlHelper.ExecuteDataTable("select * from "+tableName+"");
                //给表设置主键,方便查找.
                dt.PrimaryKey=new[] {(dt.Columns[columnKey])};
            }

            //依次保存对象属性到数据库
            foreach (PropertyInfo pi in propertys)
            {
                //获取属性值
                var a = pi.GetValue(t, null);
                //值为NULL跳出,不保存,进入下个循环
                if (a == null)
                {
                    SqlHelper.ExecuteNonQuery("delete from "+tableName+" where "+columnKey+" ='"+pi.Name+"' ");
                    continue;
                }

                //准备sql参数
                SqlParameter[] parameters = SqlHelper.CreatParameters(
                    new string[] { "Key", "Value" ,"Type"},
                    new object[] { pi.Name, a, a.GetType().ToString() }
                    );

                //查找属性是否已经存在于数据库中
                if(dt.Rows.Contains(pi.Name))
                {
                    //存在 更新属性
                    SqlHelper.ExecuteNonQuery(
                        "update " + tableName + " set " + columnValue + " = @Value , " + columnType + " = @Type where " + columnKey + " = @Key",
                        parameters
                        );
                }
                else
                {
                    //不存在 插入属性
                    SqlHelper.ExecuteNonQuery(
                        "insert into " + tableName + " (" + columnKey + "," + columnValue + "," + columnType + ") values (@key,@value,@type) ",
                        parameters
                        );
                }
            }
        }
    }
}


该类用到了两个外部类,一个是SqlHelper 就是普通的数据库辅助类,只用到了根据Sql语句和参数进行查询,更新,插入的功能,可以替换为自己的Helper类或者直接在此类中完成数据库操作

另外一个是把DataRow转换为Model对象的类,这个类是一个扩展方法,引用之后就可以直接对DataRows实例进行ToModel操作了.

return temp.Rows[0].ToModel<T>();

Sqlhelper类不再贴出,可以自己查找.扩展方法见本文:http://www.chengchenxu.com/Article/10/

本博客源码中也使用了此类,可以关注后期整理好源码后会开源,可以参考用法.

使用方法很简单:

1 这四个属性对应数据库中的表名以及列名,可以自定义,例如下图这样.

        private readonly string tableName = "blog_Config";//表名
        private readonly string columnKey = "c_Key";//key列名
        private readonly string columnValue = "c_Value";//Value列名
        private readonly string columnType = "c_Type";//Type列名


Screen Shot 2018-03-10 at 15.26.58 PM.png

key要设置为主键,类型都为varchar,长度视情况而定.


2 数据库链接字符串都是sqlHelper类中定义,SqlHelper类参考文章:http://www.chengchenxu.com/Article/11/sqlhelper


3 创建一个Model

public class ConfigSeoModel
{
        [Display(Name = "Meta关键字")]
        public string KeyWord { get; set; }
        [Display(Name = "Meta描述")]
        public string Description { get; set; }
}

//
ConfigModelDAL dal=new ConfigModelDAL();

//new 一个Model

ConfigSeoModel model=new ConfigSeoModel();
model.KeyWord="关键字";
model.Description = "描述"

//完成保存
dal.Save<ConfigSeoModel>(model);

 
//读取
ConfigSeoModel model = dal.Load<ConfigModel>();


asp.net MVC通用分页组件 使用方便 通用性强

该分页控件的显示逻辑:


1 当前页面反色突出显示,链接不可点击

2 第一页时首页链接不可点击

Screen Shot 2018-03-10 at 12.30.53 PM.png

3 最后一页时尾页链接不可点击

Screen Shot 2018-03-10 at 12.31.32 PM.png

4 当前页面左右各显示页码可以设置调节,如果左右一样则居中

Screen Shot 2018-03-10 at 12.32.02 PM.png

5 当左边页码不足时,右侧补充

Screen Shot 2018-03-10 at 12.32.29 PM.png

6 当右侧页面不足时左侧补充

Screen Shot 2018-03-10 at 12.33.21 PM.png

7 总显示页码数为左侧+右侧+1(当前)


组成部分:


1 PageModel 便于向组件传递参数

    public class PageModel
    {
        /// <summary>
        /// 数据总条数
        /// </summary>
        public int DataCount { get; set; }
        /// <summary>
        /// 当前页码
        /// </summary>
        public int Page { get; set; }
        /// <summary>
        /// 每页条数
        /// </summary>
        public int PageSize { get; set; }
        /// <summary>
        /// 当前页码左边显示页数
        /// </summary>
        public int NumsOfLeft { get; set; }
        /// <summary>
        /// 当前页码右边显示页数
        /// </summary>
        public int NumsOfRight { get; set; }
        /// <summary>
        /// 每页允许显示的最大条数
        /// 如果PageSize大于MaxPage则以MaxPage为准
        /// </summary>
        public int MaxPage { get; set; }
        /// <summary>
        /// 页面前面的URL
        /// 比如URL为http://www.chengchenxu.com/1 
        /// 1为页码,则该属性应该设置为:
        /// http://www.chengchenxu/
        /// </summary>
        public string Url { get; set; }

        public PageModel()
        {
            //设置的默认值
            this.PageSize = 10;
            this.NumsOfLeft = 4;
            this.NumsOfRight = 4;
            this.MaxPage = 30;
        }


2 分部视图: 这是一个强类型View,最上面的要对应到你的项目的命名空间中.

@model ChengChenXu.com.PageModel.Models.PageModel

<ul class="pagination">
    @{
        //页码逻辑运算
        double d = (double)Model.DataCount / Model.PageSize;
        int pageNum = (int)Math.Ceiling(d);
        Model.Page = Model.Page < 1 ? 1 : Model.Page;
        Model.Page = Model.Page > pageNum ? pageNum : Model.Page;
        Model.PageSize = Model.PageSize > Model.MaxPage ? Model.MaxPage : Model.PageSize;
        int startNum, endNum;
        if (Model.Page > Model.NumsOfLeft)
        {
            endNum = Model.Page + Model.NumsOfRight;
        }
        else
        {
            endNum = Model.Page + Model.NumsOfRight + (Model.NumsOfLeft - Model.Page + 1);
        }
        if (pageNum - Model.Page >= Model.NumsOfRight)
        {
            startNum = Model.Page - Model.NumsOfLeft;
        }
        else
        {
            startNum = Model.Page - Model.NumsOfLeft - (Model.NumsOfRight - (pageNum - Model.Page));
        }
        startNum = startNum < 1 ? 1 : startNum;
        endNum = endNum > pageNum ? pageNum : endNum;
        //END 页码逻辑运算

        //开始显示页码
        
        //显示首页
        if (pageNum == 1 || Model.Page == 1)
        {
            <li class="disabled"><a href="#" onclick="return false;">&laquo;</a></li>
        }
        else
        {
            <li><a href="@Model.Url">&laquo;</a></li>
        }
        //END 显示首页

        //显示页码
        for (int i = startNum; i <= endNum; i++)
        {
            if (i == Model.Page)
            {
                <li class="active"><a href="#" onclick="return false;">@i</a></li>
            }
            else
            {
                <li><a href="@Model.Url@i">@i</a></li>
            }

        }
        //END 显示页码

        //显示尾页
        if (pageNum == 1 || Model.Page == pageNum)
        {
            <li class="disabled"><a href="#" onclick="return false;">&raquo;</a></li>
        }
        else
        {
            <li><a href="@Model.Url@pageNum">&raquo;</a></li>
        }
        //END 显示尾页
    }
</ul>


使用方法:

1 在需要使用的地方添加以下代码:

第一个参数为分部View的文件名,(要放到Shared文件夹中)

第二个参数为页面使用ViewBag传进来的PageModel对象 注意命名空间和ViewBag的动态标签

@Html.Partial("PagePartial", ViewBag.PageModel as ChengChenXu.com.PageModel.Models.PageModel)

2 在Controller中创建PageModel对象并使用ViewBag传递

        public ActionResult Index(int id=1,int pagesize=10)
        {
            //模拟200条数据
            List<string> list = new List<string>();
            for (int i = 1; i <= 200; i++)
            {
                list.Add("第"+i+"条数据");
            }

            ViewBag.List = list;


            //创建PageModel对象
            Models.PageModel pm = new Models.PageModel();
            pm.DataCount = list.Count;//数据总条数
            pm.Page = id;//当前页码
            pm.PageSize = pagesize;//每页数量
            pm.Url = "/home/index/"; //URL

            ViewBag.PageModel = pm; //传递PageModel


            return View();
        }


生成代码

样式表请自己设计 DEMO中直接使用Bootstrap框架分页样式.

          <ul class="pagination">
            <li class="disabled"><a href="#" onclick="return false;">&laquo;</a></li>
                <li class="active"><a href="#" onclick="return false;">1</a></li>
                <li><a href="/home/index/2">2</a></li>
                <li><a href="/home/index/3">3</a></li>
                <li><a href="/home/index/4">4</a></li>
                <li><a href="/home/index/5">5</a></li>
                <li><a href="/home/index/6">6</a></li>
                <li><a href="/home/index/7">7</a></li>
                <li><a href="/home/index/8">8</a></li>
                <li><a href="/home/index/9">9</a></li>
            <li><a href="/home/index/20">&raquo;</a></li>
          </ul>


源码和DEMO下载:

ChengChenXu.com.PageModel.rar


.NET C#生成随机颜色,可以控制亮度,生成暗色或者亮色 基于YUV模式判断颜色明亮度

    随机颜色在日常开发中很常用到,有时候要控制颜色明亮度,比如在白色背景网页上的随机颜色,一般要求颜色稍微暗一些,如果生成太亮的颜色会造成阅读困难,再比如你想判断生成的背景色是暗色还是亮色,以决定前景色是白色还是黑色.

    采用YUV颜色模式来进行判断会比较合理与直观.

    

    YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号B-Y(即U)、R-Y(即V),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的


    以上红色部分解释了这个方法的合理性与准确性,具体的信息可以搜索YUV来进行更进一步的了解,RGB可以换算成YUV值,其中,我们只需要利用Y值即可,其他的暂时不用理会,换算公式如下:

       Y = 0.299R + 0.587G + 0.114B 

    两点:1 Y值范围为0-255

            2 Y值越大,颜色越亮

    核心代码部分:

        /// <summary>
        /// 根据自定义范围生成颜色
        /// </summary>
        /// <param name="start">起始数值 0-255</param>
        /// <param name="end">结束数值 0-255</param>
        /// <returns>Color</returns>
        private static Color MarkColor(int start,int end)
        {

            if (start < 0 || start > 255) throw new Exception("起始数值只能为0-255之间的数字");
            if (end < 0 || end > 255) throw new Exception("结束数值只能为0-255之间的数字");
            if (start > end) throw new Exception("起始数值不能大于结束数值");


            Random ran = new Random(Guid.NewGuid().GetHashCode());

            int R, G, B;
            double Y;            
            bool result;

            do
            {
                R = ran.Next(0, 255);
                G = ran.Next(0, 255);
                B = ran.Next(0, 255);

                //Y值计算公式
                Y = 0.299 * R + 0.587 * G + 0.114 * B;

                result = Y >= start && Y <= end;
            } while (!result);

            return Color.FromArgb(R, G, B);
        }

    为了使用更加方便,我把方法封装成了一个类库,提供了以下几个静态方法:

public static Color MakeDarkColor(int borderline = 180); //获取暗色 默认小于180
public static Color MakeLightColor(int borderline = 180); //获取亮色 默认大于180
public static Color MakeAllColor(); //获取所有颜色
public static Color MakeColorByDefine(int start, int end); //根据范围获取颜色
public static int GetY(Color color); //获取颜色Y值

    使用时只需要引用命名空间即可使用MarkRandomColor类的以上静态方法

using ChengChenXu.com.MakeRandomColor;

    使用示例:

Color color = MakeRandomColor.MarkLightColor();
Color color = MakeRandomColor.MarkDarkColor(150);
Color color = MakeRandomColor.MarkAllColor();


    最后,文件下载:

类库:

ChengChenXu.com.MakeRandomColor.rar

源码与示例:

demo.rar



微软官方SqlHelper类以及辅助访问类 简化使用方法

    微软官方SqlHelper类功能强大,但是有些地方使用起来不太方便,例如每个方法都需要传入connectionString和CommandType参数,比较繁琐. 在不修改官方类的前提下可以使用此中间类间接简化访问,此类可以很方便的进行修改和增加调用方法.

  此类引用了官方类命名空间,在使用时只需要引入此类的命名空间即可,无需在额外引入官方类的命名空间.

  以下为辅助类,官方类见下方附件.  

/// <summary>
/// 类 说 明:微软官方SqlHelper类辅助类
///           微软官方SqlHelper类功能强大,但是有些地方使用起来不太方便,例如每个方法都需要传入connectionString和CommandType参数,比较繁琐.
///           在不修改官方类的前提下可以使用此中间类间接简化访问,此类可以很方便的进行修改和增加调用方法.
///           此类引用了官方类命名空间,在使用时只需要引入此类的命名空间即可,无需在额外引入官方类.
/// 编 码 人:程晨旭
/// 联系方式:Email:97391519@qq.com 
///           Blog:http://chengchenxu.com
/// 修改日期:2018-02-28
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SQLHelper;

namespace ChengChenXu.DAL.SqlServer
{
    public class SqlServerHelper
    {
        private static readonly string connectionString = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["sqlserver"].ConnectionString;

        public SqlServerHelper() { }

        /// <summary>
        /// 格式化参数组,将键值对插入到SqlParameters数组中
        /// </summary>
        /// <param name="paramsName">参数名数组string[]</param>
        /// <param name="paramsValues">参数值数组object[]</param>
        /// <returns>SqlParameter[]</returns>
        public static SqlParameter[] CreatParameters(string[] paramsName, object[] paramsValues)
        {
            if (paramsName.Length != paramsValues.Length)
                throw new AggregateException("参数和值数量不一致");

            SqlParameter[] parameters = new SqlParameter[paramsName.Length];

            for (int i = 0; i < paramsName.Length; i++)
            {
                SqlParameter parameter = new SqlParameter(paramsName[i], paramsValues[i]);
                parameters[i] = parameter;
            }

            return parameters;
        }

        /// <summary>
        /// 执行一条无参数Insert、Update、Del命令,CommandType默认值为CommandType.Text,返回受影响的行数。
        /// </summary>
        /// <param name="commandText">sql语句</param>
        /// <returns>int32</returns>
        public static int ExecuteNonQuery(string commandText)
        {
            return MicrosoftSqlHelper.ExecuteNonQuery(connectionString, CommandType.Text, commandText);
        }

        /// <summary>
        /// 执行一条含有参数Insert、Update、Delete命令,CommandType默认值为CommandType.Text,返回受影响的行数。
        /// </summary>
        /// <param name="commandText">sql语句</param>
        /// <param name="commandParameters">参数组</param>
        /// <returns>int32</returns>
        public static int ExecuteNonQuery(string commandText, params SqlParameter[] commandParameters)
        {
            return MicrosoftSqlHelper.ExecuteNonQuery(connectionString, CommandType.Text, commandText, commandParameters);
        }

        /// <summary>
        /// 执行一条无参数的Select语句,返回DataTable。
        /// </summary>
        /// <param name="commandText">sql语句</param>
        /// <returns>DataTable</returns>
        public static DataTable ExecuteDataTable(string commandText)
        {
            return MicrosoftSqlHelper.ExecuteDataset(connectionString, CommandType.Text, commandText).Tables[0];
        }

        /// <summary>
        /// 执行一条包含参数的Select语句,默认CommandType.Text,返回DataTable。
        /// </summary>
        /// <param name="commandText">sql语句</param>
        /// <param name="commandParameters">参数组</param>
        /// <returns>DataTable</returns>
        public static DataTable ExecuteDataTable(string commandText, params SqlParameter[] commandParameters)
        {
            return MicrosoftSqlHelper.ExecuteDataset(connectionString, CommandType.Text, commandText, commandParameters).Tables[0];
        }
       
        /// <summary>
        /// 执行一条sql语句获取首行首列,默认CommandType.Text
        /// </summary>
        /// <param name="commandText">sql语句</param>
        /// <param name="commandParameters">参数组</param>
        /// <returns>object</returns>
        public static object ExecuteScalar(string commandText, params SqlParameter[] commandParameters)
        {
            return MicrosoftSqlHelper.ExecuteScalar(connectionString, CommandType.Text, commandText, commandParameters);
        }
    }
}

附件下载:

SqlHelper.rar


原创文章,转载请注明出处.

DataTable和DataRow利用反射直接转换为Model对象的扩展方法类

/// <summary>
/// 类 说 明:给DataTable和DataRow扩展方法,直接转换为对象集合或对象
/// 编 码 人:程晨旭
/// 联系方式:Email:97391519@qq.com 
///           Blog:http://chengchenxu.com
/// 修改日期:2018-02-28
/// 补充说明:此扩展类可以极大的简化操作,但是性能低下,大数据以及高性能要求下慎用.
///           此类如果放到asp.net的App_Code文件夹下会有编译错误,放到其他地方则无此问题
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Reflection;

namespace ChengChenXu.DataTableExtensions
{
    
    public static class DataTableExtensions
    {
        /// <summary>
        /// 把DataRow直接转换成对应的实体对象,给DataRow添加一个扩展方法,方便使用.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dr"></param>
        /// <returns></returns>
        public static T ToModel<T>(this DataRow dr)
        {
            T t = Activator.CreateInstance<T>();
            // 利用反射获得此模型的公共属性  
            string attributeName = String.Empty;
            PropertyInfo[] propertys = t.GetType().GetProperties();
            foreach (PropertyInfo pi in propertys)
            {
                attributeName = pi.Name;
                // 检查DataTable是否包含此列
                //此处要求DataRow的列名称要和对象属性名称一致
                //注意:此处大小写不敏感
                if (dr.Table.Columns.Contains(attributeName))
                {
                    // 判断此属性是否为只读(不包含set构造)  
                    if (!pi.CanWrite) { continue; }

                    //给属性赋值
                    var value = dr[attributeName];
                    if (value != DBNull.Value) 
                    { 
                        pi.SetValue(t, value, null); 
                    }
                }
            }
            return t;
        }

        /// <summary>
        /// 将DataTable直接转化为对象集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static List<T> ToModelList<T>(this DataTable dt)
        {
            List<T> list = new List<T>();

            //调用ToModel方法添加List
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                T t = Activator.CreateInstance<T>();
                t = dt.Rows[i].ToModel<T>();
                list.Add(t);
            }

            return list;
        }
    }
}


使用方法:直接引用命名空间之后可以直接使用该方法

public List<LinkModel> GetLinkList()
        {
            DataTable dt = SqlServerHelper.ExecuteDataTable("select * from MVC_Link order by showOrder ASC ");

            return dt.ToModelList<LinkModel>(); 
        }
        
        
        public LinkModel GetLink(int id)
        {
            string sql = "select * from MVC_Link where id = @id";
            SqlParameter[] parameters = SqlServerHelper.CreatParameters(
                new string[] { "id" },
                new object[] { id }
                );

            DataTable dt = SqlServerHelper.ExecuteDataTable(sql, parameters);

            return dt.Rows[0].ToModel<LinkModel>();
        }



点击直接下载类文件:

DataTableExtensions.rar


首页 1 尾页