zoukankan      html  css  js  c++  java
  • 玩转控件:扩展Dev中SimpleButton

        何为扩展,顾名思义,就是在原有控件属性、事件的基础上拓展自己需要或实用的属性、事件等等。或者可以理解为,现有的控件已经不能完全满足我(的需求)了。好的扩展会使控件更加完善,实用,好用。不好的扩展,说白了就是画蛇添足!好了,跟着博主一起玩转控件吧,看看您在实际项目运用中是否也曾几何时遇到过这样的困惑。

            本篇拿一个简单的Dev控件为例,件如其名——SimpleButton,一个成熟的软件,一定会考虑到所有人的操作习惯以及简洁舒适的界面。做人如是,控件如是。

            本篇缘起于博主最近削尖脑袋,硬着头皮看英文文档。那家伙把我读的,那场面,那气势,真是锣鼓喧天鞭炮起,红旗招展,文山文海... 大部分它认识我,我不认识它。最后还得靠多年酝酿的Google大法才能拨开云雾见青天。偶然间联想到最近预热的《手撕ERP》(FuckingERP)之控件系列,公众号私信里面有很多国外的朋友,拿到源码,信誓旦旦的按下F5傻眼了。全是中文字,而且有的还乱码。

       因此,鉴于此,从本篇起,后续所有控件系列都会扩展一个多语言的属性功能(俗称国际化)。多语言功能有很多实现方式,博主之前也实践过很多方式,比如资源文件处理、展示界面前调用Google翻译后赋值等等,这些方式有利有弊,本篇博主将采用另外一种方式来实现多语言-数据库存储,键值对取值的方式。巴拉巴拉巴拉.....

            扯远了扯远了,回归主题,还是来看看博主是怎么扩展按钮的吧!

            Talk is Cheap,Show me the Code!

            首先,新建一个用户控件,并让其继承Dev原始控件SimpleButton

    public partial class KzxSimpleButton : SimpleButton, ILayoutControl

        后面的ILayoutControl接口,是我用来定义要实现的属性和事件的,部分代码如下:

    /// <summary>
    /// 没有多语言的情况下的默认显示标题
    /// </summary>
    string DesigeCaption { get; set; }
    /// <summary>
    /// 设计时的可用性
    /// </summary>
    bool DesigeEnabled { get; set; }
    /// <summary>
    /// 设计时可见性
    /// </summary>
    bool DesigeVisible { get; set; }
    /// <summary>
    /// 控件的唯一标识
    /// </summary>
    string Key { get; set; }
    /// <summary>
    /// 布局列号
    /// </summary>
    int LayoutColumn { get; set; }
    /// <summary>
    /// 布局跨的列数
    /// </summary>
    int LayoutColumnSpan { get; set; }
    /// <summary>
    /// 布局行号
    /// </summary>
    int LayoutRow { get; set; }
    /// <summary>
    /// 布局跨的行数
    /// </summary>
    int LayoutRowSpan { get; set; }
    /// <summary>
    /// 多语言环境下显示文本的对应标识
    /// </summary>
    string MessageCode { get; set; }
    
    /// <summary>
    /// 事件插件信息表
    /// </summary>
    DataTable PluginInfoTable { get; set; }
    
    /// <summary>
    /// 事件列表
    /// </summary>
    string EventList { get; set; }
    
    /// <summary>
    /// 提示信息
    /// </summary>
    string ToolTipText { get; set; }
    
    /// <summary>
    /// 提示多语言标识
    /// </summary>
    string ToolTipMessageCode { get; set; }
    
    /// <summary>
    /// 绑定事件
    /// </summary>
    /// <param name="valueControl">控件</param>
    /// <param name="eventInfoTable">事件信息表</param>
    void BindingEvent(Control valueControl, DataTable eventInfoTable);
    
    /// <summary>
    /// 设置布局
    /// </summary>
    void SetLayout();
    
    /// <summary>
    /// 控件被加载后调用的方法
    /// 此方法在控件还原后被窗口调用
    /// </summary>
    void KzxControlLoaded();
    
    /// <summary>
    /// 控件事件
    /// </summary>
    event KzxControlOperateEventHandler KzxControlOperate;
    /// <summary>
    /// 获取多语言文本事件
    /// </summary>
    event KzxGetLanguageEventHandler KzxGetLanguage;

      然后在刚刚新建的用户控件实现这个接口,部分代码如下:

    #region 布局属性
      private int _LayoutRow = 0;
      /// <summary>
      /// 布局行号
      /// </summary>
      [Category("布局"), Description("LayoutRow,布局行号"), Browsable(false)]
      [McDisplayName("LayoutRow")]
      public int LayoutRow
      {
          get
          {
              if (this.DesignMode == true)
              {
                  TableLayoutPanel panel = this.Parent as TableLayoutPanel;
                  if (panel != null)
                  {
                      this._LayoutRow = panel.GetRow(this);
                  }
              }
              return this._LayoutRow;
          }
          set
          {
              this._LayoutRow = value;
              if (this.DesignMode == true)
              {
                  TableLayoutPanel panel = this.Parent as TableLayoutPanel;
                  if (panel != null)
                  {
                      panel.SetRow(this, value);
                  }
              }
          }
      }
    
      private int _LayoutRowSpan = 1;
      /// <summary>
      /// 布局跨的行数
      /// </summary>
      [Category("布局"), Description("LayoutRowSpan,布局跨的行数"), Browsable(false)]
      [McDisplayName("LayoutRowSpan")]
      public int LayoutRowSpan
      {
          get
          {
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  panel.SetRowSpan(this, this._LayoutRowSpan);
              }
              return this._LayoutRowSpan;
          }
          set
          {
              this._LayoutRowSpan = value;
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  panel.SetRowSpan(this, value);
              }
          }
      }
    
      private int _LayoutColumn = 0;
      /// <summary>
      /// 布局列号
      /// </summary>
      [Category("布局"), Description("LayoutColumn,布局列号"), Browsable(false)]
      [McDisplayName("LayoutColumn")]
      public int LayoutColumn
      {
          get
          {
              if (this.DesignMode == true)
              {
                  TableLayoutPanel panel = this.Parent as TableLayoutPanel;
                  if (panel != null)
                  {
                      this._LayoutColumn = panel.GetColumn(this);
                  }
              }
              return this._LayoutColumn;
          }
          set
          {
              this._LayoutColumn = value;
              if (this.DesignMode == true)
              {
                  TableLayoutPanel panel = this.Parent as TableLayoutPanel;
                  if (panel != null)
                  {
                      panel.SetColumn(this, value);
                  }
              }
          }
      }
    
      private int _LayoutColumnSpan = 1;
      /// <summary>
      /// 布局跨的列数
      /// </summary>
      [Category("布局"), Description("LayoutColumnSpan,布局跨的列数"), Browsable(false)]
      [McDisplayName("LayoutColumnSpan")]
      public int LayoutColumnSpan
      {
          get
          {
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  panel.SetColumnSpan(this, this._LayoutColumnSpan);
              }
              return this._LayoutColumnSpan;
          }
          set
          {
              this._LayoutColumnSpan = value;
              TableLayoutPanel panel = this.Parent as TableLayoutPanel;
              if (panel != null)
              {
                  panel.SetColumnSpan(this, value);
              }
          }
      }
    
      #endregion

      为了效果明显点,博主就拿ToolTip来举例,以及部分事件代码如下:

    private string _MessageCode = "0";
      /// <summary>
      /// 多语言环境下显示文本的对应标识
      /// </summary>
      [Category("多语言"), Description("MessageCode,多语言环境下显示文本的对应标识"), Browsable(true)]
      [McDisplayName("MessageCode")]
      public virtual string MessageCode
      {
          get
          {
              return this._MessageCode;
          }
          set
          {
              this._MessageCode = value;
          }
      }
    
      private string _DesigeCaption = string.Empty;
      /// <summary>
      /// 没有多语言的情况下的默认显示标题
      /// </summary>
      [Category("多语言"), Description("DesigeCaption,没有多语言的情况下的默认显示标题"), Browsable(true)]
      [McDisplayName("DesigeCaption")]
      public virtual string DesigeCaption
      {
          get
          {
              return this.Text.Trim();
          }
          set
          {
              this.Text = value;
          }
      }

      拿ToolTip举个例子

    #region 方法
      private DataTable _PluginInfoTable = KzxBaseControl.CreatePluginDataTable();
      [Category("自定义"), Description("PluginInfoTable,事件插件信息表"), Browsable(false)]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
      [McDisplayName("PluginInfoTable")]
      public DataTable PluginInfoTable
      {
          get
          {
              return this._PluginInfoTable;
          }
          set
          {
              this._PluginInfoTable = value;
              BindingEvent(this, this._PluginInfoTable);
          }
      }
    
      private string _ToolTipText = string.Empty;
      /// <summary>
      /// 提示信息
      /// </summary>
      [Category("汽泡提示"), Description("ToolTipText,提示信息"), Browsable(true)]
      [McDisplayName("ToolTipText")]
      public virtual string ToolTipText
      {
          get
          {
              return this._ToolTipText;
          }
          set
          {
              this._ToolTipText = value;
          }
      }
    
      private string _ToolTipMessageCode = string.Empty;
      /// <summary>
      /// 提示多语言标识
      /// </summary>
      [Category("汽泡提示"), Description("ToolTipMessageCode,提示信息多语言标识"), Browsable(true)]
      [McDisplayName("ToolTipMessageCode")]
      public virtual string ToolTipMessageCode
      {
          get
          {
              return this._ToolTipMessageCode;
          }
          set
          {
              this._ToolTipMessageCode = value;
          }
      }
    
      private Color _LabelForeColor = Color.Black;
      /// <summary>
      /// 标签字体颜色
      /// </summary>
      [Category("外观"), Description("LabelForeColor,标签字体颜色"), Browsable(true)]
      [McDisplayName("LabelForeColor")]
      public Color LabelForeColor
      {
          get
          {
              return this.ForeColor;
          }
          set
          {
              this._LabelForeColor = value;
              this.ForeColor = value;
          }
      }
    
      /// <summary>
      /// 控钮类型
      /// </summary>
      [Category("外观"), Description("YZButtonStyle,控钮类型"), Browsable(true)]
      [McDisplayName("YZButtonStyle")] 
      public DevExpress.XtraEditors.Controls.BorderStyles YZButtonStyle
      {
          get
          {
              return this.ButtonStyle;
          }
          set
          {
              this.ButtonStyle = value;
          }
      }
    
      #endregion

      代码比较简单,关键属性和事件也已经添加了详细备注,就不一一解释了。用户控件创建好后,我们就可以直接实用拖控件大法了。

      效果如下:

      实现控件按钮,鼠标悬浮提示框(ToolTip)插件代码也比较简单,具体如下:

         其中ssLoadMsgOrDefault方法,就是博文开头提到的,数据库存储-键值对取值的方法,具体如下:

    /// <summary>
      /// 根据Msg_ID取相应语言描述,获取为空时显示 emptyDisplayMsg
      /// </summary>
      /// <param name="msgID"></param>
      /// <param name="emptyDisplayMsg"></param>
      /// <returns></returns>
      public static string ssLoadMsgOrDefault(string msgID, string emptyDisplayMsg)
      {
          if (string.IsNullOrWhiteSpace(msgID))
              return emptyDisplayMsg;
    
          var msgText = string.Empty;
          if (SysVar.LanguageList.ContainsKey(msgID))
              msgText = SysVar.LanguageList[msgID];
    
          if (string.IsNullOrWhiteSpace(msgText))
              msgText = emptyDisplayMsg;
    
          return msgText;
      }

      为了方便处理多语言,博主还写了个小软件,用来存储或生成多语言对应关系,这个后续会给大家介绍,好了,让我们F5来看看具体效果:

      最后,由于后续所有重写/重绘控件都在同一个项目使用,而且Dev系统引用文件较多,压缩后源码文件仍然很大,如果有需要源码的朋友,可以微信公众号联系博主,源码可以免费赠予~!有疑问的也可以CALL我一起探讨,最最后,如果觉得本篇博文对您或者身边朋友有帮助的,麻烦点个关注!赠人玫瑰,手留余香,您的支持就是我写作最大的动力,感谢您的关注,期待和您一起探讨!再会!

     

  • 相关阅读:
    Selenium Webdriver元素定位的八种常用方式【转】
    python学习笔记(3)函数、参数、变量、递归
    Python学习总结
    Webdriver API (二)
    Webdriver API (一)
    解决Selenium弹出新页面无法定位元素问题(Unable to locate element)
    selenium之 定位以及切换frame(iframe)
    第一篇博客
    自制DTU
    DTU软硬件方案
  • 原文地址:https://www.cnblogs.com/axing/p/12555830.html
Copyright © 2011-2022 走看看