当前位置: 首页 > news >正文

C#:为详情查看界面设计的万用TextBox自定义控件

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在写C#的Winform页面的时候,经常会遇到下面的问题:

一个详情查看类的页面,控件是从相关录入页面复制来的。为了让控件不可编辑,经常要设置控件的Enabled属性为False,或ReadOnly属性为True(如TextBox)等。但这样做最大的坏处就是造成了界面风格的不统一,如果字体、字号、风格、颜色都不统一,界面就会显得非常难看。

为此我设计了一个自定义控件,继承自TextBox,目的是让界面风格统一,原型效果如下:

(以上两张原型图使用Balsamiq绘制)

我设计的控件MultiFuncViewTextBox代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustuomControl
{
    public class MultiFuncViewTextBox : TextBox
    {
        public MultiFuncViewTextBox()
        {
            this.SuspendLayout();
            this.ReadOnly = true;
            this.ResumeLayout(false);
        }

        /// <summary>
        /// 控件是否已初始化
        /// </summary>
        private bool _isInitialized;
        /// <summary>
        /// 控件是否已初始化:可设定如果已初始化不允许再次初始化
        /// 如不需设定则将set置为永远返回false即可
        /// </summary>
        public bool IsInitialized
        {
            get
            {
                return _isInitialized;
            }
            private set
            {
                _isInitialized = value;
            }
        }

        /// <summary>
        /// 控件功能
        /// </summary>
        private FuncType _textFuncType;
        /// <summary>
        /// 控件功能:不同的功能会对传入的参数进行不同的处理
        /// </summary>
        public FuncType TextFuncType
        {
            get
            {
                return _textFuncType;
            }
            private set
            {
                _textFuncType = value;
            }
        }

        /// <summary>
        /// 初始化时传入的原始数据
        /// </summary>
        private object _coreValue;
        /// <summary>
        /// 初始化时传入的原始数据
        /// </summary>
        public object CoreValue
        {
            get
            {
                return _coreValue;
            }
            private set
            {
                _coreValue = value;
            }
        }

        /// <summary>
        /// 精度 - 保留小数位数(仅作用于BigChnNum和BigChnCash)
        /// </summary>
        private int _precision = 2;
        /// <summary>
        /// 精度 - 保留小数位数(仅作用于BigChnNum和BigChnCash)
        /// </summary>
        public int Precision
        {
            get
            {
                return _precision;
            }
            set
            {
                if (value < 0)
                {
                    throw new Exception("精度值不能小于0");
                }
                if (value > 10) //可根据项目情况酌情修改最大容忍精度
                {
                    throw new Exception("精度值不能大于10");
                }
                _precision = value;
            }
        }

        /// <summary>
        /// 是否需要显示汉字大写数字(仅作用于BigChnNum和BigChnCash)
        /// </summary>
        private bool _needChineseNumerals;
        /// <summary>
        /// 是否需要显示汉字大写数字(仅作用于BigChnNum和BigChnCash)
        /// </summary>
        public bool NeedChineseNumerals
        { 
            get
            {
                return _needChineseNumerals;
            }
            set
            {
                _needChineseNumerals = value;
            }
        }

        /// <summary>
        /// 数据字典主项(仅作用于DataDic)
        /// </summary>
        private string _dataDicEntry;
        /// <summary>
        /// 数据字典主项(仅作用于DataDic)
        /// </summary>
        public string DataDicEntry
        {
            get
            {
                return _dataDicEntry;
            }
            set
            {
                _dataDicEntry = value;
            }
        }

        private ToolTip toolTip = new ToolTip();
        
        /// <summary>
        /// 初始化控件
        /// </summary>
        /// <param name="val"></param>
        /// <param name="funcType"></param>
        public void InitCoreValue(object val, FuncType funcType)
        {
            if (IsInitialized && funcType != TextFuncType)
            {
                throw new Exception("不能改变控件用途");
            }

            switch (funcType)
            {
                case FuncType.Simple:
                    {
                        this.Text = "";

                        if (val != null)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.Simple;
                            this.Text = val.ToString();
                        }
                    }
                    break;
                case FuncType.BigChnNum:
                    {
                        this.Text = "";

                        if (val is decimal)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.BigChnNum;
                            decimal dVal = (decimal)val;
                            this.Text = String.Format("{0:N" + Precision + "}", dVal);
                            if (!IsInitialized && NeedChineseNumerals)
                            {
                                toolTip = new ToolTip();// 气泡弹窗
                                toolTip.IsBalloon = false;// 不显示为气泡弹窗,气泡的箭头会乱跑
                                toolTip.SetToolTip(this, "");
                                toolTip.ShowAlways = true;// 总是显示
                                toolTip.UseAnimation = true;
                                toolTip.UseFading = true;
                                this.Enter += (arg, obj) =>
                                {
                                    try
                                    {
                                        toolTip.Hide(this);
                                        toolTip.Show(RMBToChr2(decimal.Parse(this.Text)), this, 0, -22, 3000);
                                    }
                                    catch (Exception ex)
                                    {
                                        MessageBox.Show(ex.Message);
                                    }
                                };
                                this.Leave += (arg, obj) =>
                                {
                                    try
                                    {
                                        toolTip.Hide(this);
                                    }
                                    catch (Exception ex)
                                    {
                                        MessageBox.Show(ex.Message);
                                    }
                                };
                            }
                        }
                    }
                    break;
                case FuncType.BigChnCash:
                    {
                        this.Text = "";

                        if (val is decimal)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.BigChnCash;
                            decimal dVal = (decimal)val;
                            this.Text = String.Format("{0:N" + Precision + "}", dVal);
                            if (!IsInitialized && NeedChineseNumerals)
                            {
                                ToolTip toolTip = new ToolTip();// 气泡弹窗
                                toolTip.IsBalloon = false;// 不显示为气泡弹窗,气泡的箭头会乱跑
                                toolTip.SetToolTip(this, "");
                                toolTip.ShowAlways = true;// 总是显示
                                toolTip.UseAnimation = true;
                                toolTip.UseFading = true;

                                this.Enter += (arg, obj) =>
                                {
                                    try
                                    {
                                        toolTip.Hide(this);
                                        toolTip.Show(RMBToChr(decimal.Parse(this.Text)), this, 0, -22, 3000);
                                    }
                                    catch (Exception ex)
                                    {
                                        MessageBox.Show(ex.Message);
                                    }
                                };
                                this.Leave += (arg, obj) =>
                                {
                                    try
                                    {
                                        toolTip.Hide(this);
                                    }
                                    catch (Exception ex)
                                    {
                                        MessageBox.Show(ex.Message);
                                    }
                                };
                            }
                        }
                    }
                    break;
                case FuncType.Date:
                    {
                        this.Text = "";

                        DateTime dtVal = new DateTime();
                        if (val is int || val is long)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.Date;
                            dtVal = DateTime.ParseExact(val.ToString(), "yyyyMMdd", null);
                            this.Text = dtVal.ToLongDateString();
                        }
                        else if (val is DateTime)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.Date;
                            dtVal = (DateTime)val;
                            this.Text = dtVal.ToLongDateString();
                        }
                    }
                    break;
                case FuncType.Time:
                    {
                        this.Text = "";

                        DateTime dtVal = new DateTime();
                        if (val is int || val is long)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.Time;
                            dtVal = DateTime.ParseExact(val.ToString(), "HHmmss", null);
                            this.Text = dtVal.ToLongTimeString();
                        }
                        else if (val is DateTime)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.Time;
                            dtVal = (DateTime)val;
                            this.Text = dtVal.ToLongTimeString();
                        }
                    }
                    break;
                case FuncType.DataDic:
                    {
                        this.Text = "";

                        string dicEntry = "";
                        string subDicEntry = "";
                        if (val is KeyValuePair<string, string>)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.DataDic;
                            KeyValuePair<string, string> pair = (KeyValuePair<string, string>)val;
                            dicEntry = pair.Key;
                            subDicEntry = pair.Value;
                        }
                        else if (val is string)
                        {
                            this.CoreValue = val;
                            this.TextFuncType = FuncType.DataDic;
                            dicEntry = DataDicEntry;
                            subDicEntry = val.ToString();
                        }
                        if (!string.IsNullOrWhiteSpace(dicEntry) && !string.IsNullOrWhiteSpace(subDicEntry))
                        {
                            //TODO:获取对应数据字典值
                            this.Text = "TODO:获取对应数据字典值";
                        }
                    }
                    break;
            }

            IsInitialized = true;
        }

        public static string RMBToChr(decimal x)
        {
            string s = x.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
            string d = Regex.Replace(s, @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
            return Regex.Replace(d, ".", m => "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟萬億兆京垓秭穰"[m.Value[0] - '-'].ToString());
        }

        public static string RMBToChr2(decimal x)
        {
            string s = x.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#");
            string d = Regex.Replace(s, @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
            string integerPart = Regex.Replace(d, ".", m => "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟萬億兆京垓秭穰"[m.Value[0] - '-'].ToString());
            if (integerPart == "")
            {
                integerPart = "零";
            }

            string fractionalPart = "";
            if (x.ToString().IndexOf('.') != -1)
            {
                fractionalPart = x.ToString().Substring(x.ToString().IndexOf('.'));
                fractionalPart = fractionalPart.Replace(".", "点");
                fractionalPart = fractionalPart.Replace("0", "零");
                fractionalPart = fractionalPart.Replace("1", "壹");
                fractionalPart = fractionalPart.Replace("2", "贰");
                fractionalPart = fractionalPart.Replace("3", "叁");
                fractionalPart = fractionalPart.Replace("4", "肆");
                fractionalPart = fractionalPart.Replace("5", "伍");
                fractionalPart = fractionalPart.Replace("6", "陆");
                fractionalPart = fractionalPart.Replace("7", "柒");
                fractionalPart = fractionalPart.Replace("8", "捌");
                fractionalPart = fractionalPart.Replace("9", "玖");
            }

            return integerPart + fractionalPart;
        }
    }
}

其中FuncType是一个枚举,包括以下类型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CustuomControl
{
    /// <summary>
    /// 多功能显示文本框功能类型
    /// </summary>
    public enum FuncType
    {
        /// <summary>
        /// 普通类型
        /// </summary>
        Simple = 0,
        /// <summary>
        /// 大写汉字(普通)
        /// </summary>
        BigChnNum = 1,
        /// <summary>
        /// 大写汉字(金额)
        /// </summary>
        BigChnCash = 2,
        /// <summary>
        /// 日期
        /// </summary>
        Date = 3,
        /// <summary>
        /// 时间
        /// </summary>
        Time = 4,
        /// <summary>
        /// 数据字典类型
        /// </summary>
        DataDic = 5
    }
}

上面的控件有如下特点:

1、控件风格统一。平心而论,详情查看类页面只需要显示结果,不需要放置很多功能性控件(如下拉菜单ComboBox、日期时间选择控件DateTimePicker等),只需要一个TextBox控件就可以了。

2、CoreValue存储了用户存入控件的原始数据,通过控件的Text属性可取出控件处理后的数据。

3、BigChnNum和BigChnCash两种控件使用类型,支持Precision(精度)和NeedChineseNumerals(是否需要用气泡展示汉字大写金额)。

4、如果控件用途设置为BigChnNum,则气泡中显示大写数字; 如果控件用途设置为 BigChnCash ,则气泡中显示大写数字金额,并添加单位圆、角、分。

5、如果控件用途设置为DataDic,可手动设置DataDicEntry属性,指定数据字典号。

6、初始化统一使用函数InitCoreValue,使用方法为InitCoreValue(要传入的数据,控件用途)

public void InitCoreValue(object val, FuncType funcType)

下面用一个例子说明这个控件的用法。

界面控件放置如下:

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UserControlTest
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            try
            {
                //查看类界面万用控件
                //一般使用
                mfvNormal.InitCoreValue("你好", CustuomControl.FuncType.Simple);
                //为数字增加千位符
                mfvChnNum.InitCoreValue(123456789.1234M, CustuomControl.FuncType.BigChnNum);
                mfvChnCash.InitCoreValue(123456789.1234M, CustuomControl.FuncType.BigChnCash);
                //为数字增加千位符,并在上方增加汉字大写气泡
                mfvChnNumWithTip.Precision = 3;
                mfvChnNumWithTip.NeedChineseNumerals = true;
                mfvChnNumWithTip.InitCoreValue(123456789.1234M, CustuomControl.FuncType.BigChnNum);
                mfvChnCashWithTip.Precision = 3;
                mfvChnCashWithTip.NeedChineseNumerals = true;
                mfvChnCashWithTip.InitCoreValue(123456789.1234M, CustuomControl.FuncType.BigChnCash);
                //显示日期
                mfvDate1.InitCoreValue(20160524, CustuomControl.FuncType.Date);
                mfvDate2.InitCoreValue(20160524L, CustuomControl.FuncType.Date);
                mfvDate3.InitCoreValue(new DateTime(2016, 5, 24), CustuomControl.FuncType.Date);
                //显示时间
                mfvTime1.InitCoreValue(140430, CustuomControl.FuncType.Time);
                mfvTime2.InitCoreValue(140430, CustuomControl.FuncType.Time);
                mfvTime3.InitCoreValue(new DateTime(2016, 5, 24, 14, 4, 30), CustuomControl.FuncType.Time);
                //显示数据字典
                mfvDataDic1.InitCoreValue(new KeyValuePair<string, string>("1001", "3"), CustuomControl.FuncType.DataDic);
                mfvDataDic2.DataDicEntry = "1001";
                mfvDataDic2.InitCoreValue("3", CustuomControl.FuncType.DataDic);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            btnDummy.Select(); //这是一个无用的Button按钮
        }
    }
}

运行效果如下:

END

转载于:https://my.oschina.net/Tsybius2014/blog/682240

相关文章:

  • JS --事件
  • Sublime Text 3 关闭自动提示
  • 用verilog模拟DDS产生正弦波信号
  • 第k个元素(模板)
  • 景德镇特色的部门级别与权限
  • swift 字符串创建类
  • push 和pop的区别
  • linux命令行模式下实现代理上网 专题
  • tab.js分享及浏览器兼容性问题汇总
  • linux----进度条程序
  • Eclipse:The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path
  • 运行TestCase时,提示:Element is not currently visible and so may not be interacted with
  • iOS开发之UITextField的使用详解
  • 使用生成器展平异步回调结构,JS篇
  • IPv4 地址分类
  • JavaScript-如何实现克隆(clone)函数
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • IndexedDB
  • JavaScript 基础知识 - 入门篇(一)
  • JAVA多线程机制解析-volatilesynchronized
  • js正则,这点儿就够用了
  • MySQL QA
  • Sass 快速入门教程
  • spring-boot List转Page
  • SpringBoot 实战 (三) | 配置文件详解
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 树莓派 - 使用须知
  • 我与Jetbrains的这些年
  • 新书推荐|Windows黑客编程技术详解
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #if #elif #endif
  • #Linux(帮助手册)
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (分享)自己整理的一些简单awk实用语句
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (简单) HDU 2612 Find a way,BFS。
  • (一)SpringBoot3---尚硅谷总结
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • .apk文件,IIS不支持下载解决
  • .NET 表达式计算:Expression Evaluator
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .net6Api后台+uniapp导出Excel
  • .net获取当前url各种属性(文件名、参数、域名 等)的方法
  • .考试倒计时43天!来提分啦!
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600
  • [] 与 [[]], -gt 与 > 的比较
  • [1525]字符统计2 (哈希)SDUT
  • [20181219]script使用小技巧.txt