• 玩转控件:封装Dev的SearchLookupEdit


    鸣谢

            随着前面几个章节对控件封装与扩展的分享,不少小伙伴儿们在作者公众号上反馈,并联系作者,表示通过这些系列和源码能学到不少细节上的东西,并运用到了自己的实际项目当中,也有不少伙伴儿反馈更好更优的处理方式。作者在此感谢大家的陪伴与探讨,希望能与大家一起学习,一起进步。

    工欲善其事必先利其器

            公众号反馈最多的是《玩转控件:封装Dev的LabelControl和TextEdit》,表示运用到自己实际项目后,确实大大减少了自己的工作量,并希望能有更多这种类型的博文。为了满足小伙伴儿的心愿,作者后续会分享更多自己实际项目运用到的小技巧,希望能对更多小伙伴儿有更多的帮助和启发。最后,也希望小伙伴儿们能从作者分享对不同类型控件的封装中举一反三,扩展满足自己实际业务的插件。有好的想法,别忘记分享给作者哦,三人行,必有我师嘛~

    Talk is Cheap

              废话不多说,今天作者要分享的也是作者实际项目中遇到的问题——有数据源的下拉搜索框。不少大的企业反馈,公司职员比较多,数据量比较大,鼠标下拉寻找太过繁琐和耗时,能不能提供个更优的处理方式。经过作者一番思索,以迅雷不及掩耳盗铃响叮当之势就找到了符合客户的处理方式——就是Dev的SearchLookupEdit。

              大家也可以直接用Dev的SearchLookupEdit控件,效果还不错,当然为了方便起见,减少自己的操作量,也可以模仿《玩转控件:封装Dev的LabelControl和TextEdit》一样,自己根据实际情况做个封装,来吧!作者陪大家一起重温下封装的乐趣。


    Show me the Code

       和往常一样,新建一个类用来封装和扩展自己实际要用到的属性和事件:

     public partial class KzxSearchComboboxEdit : KzxBaseControl

            初始化的时候,就可以封装好自己要用到的事件:

    public KzxSearchComboboxEdit()
        {
            InitializeComponent();
    
            this.ValueControl.QueryPopUp += new CancelEventHandler(lookUpEdit_QueryPopUp);
            this.ValueControl.Closed += new ClosedEventHandler(lookUpEdit_Closed);
    
            this.CaptionControl.AutoSizeMode = LabelAutoSizeMode.Vertical;
            this.CaptionControl.SizeChanged += new EventHandler(SetSize);
            this.ValueControl.Enter -= new EventHandler(ValueControl_Enter);
            this.ValueControl.Enter += new EventHandler(ValueControl_Enter);
    
            this._SearchLookUpEditView.FocusRectStyle = DevExpress.XtraGrid.Views.Grid.DrawFocusRectStyle.RowFocus;
            this._SearchLookUpEditView.Name = "gridLookUpEdit1View";
            this._SearchLookUpEditView.OptionsSelection.EnableAppearanceFocusedCell = false;
            this._SearchLookUpEditView.OptionsView.ShowGroupPanel = false;
            this.ValueControl.Properties.PopupFormSize = new System.Drawing.Size((int)(this.ValueControl.Width * 2), (int)(this.ValueControl.Width * 1.5));
    
            if (this.DesignMode == true)
            {
                this.Size = new Size(284, 21);
            }
        }

            把自己实际需要用到的属性做好封装,举个栗子:

     private int _ItemIndex = -1;
      /// <summary>
      /// 选中项的下标
      /// </summary>
      [Category("自定义"), Description("ItemIndex,选中项的下标"), Browsable(false)]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
      [McDisplayName("ItemIndex")]
      public int ItemIndex
      {
          get
          {
              return this._ItemIndex;
          }
          protected set
          {
              this._ItemIndex = value;
          }
      }
      
      private DataRow _CurrentItem = null;
      /// <summary>
      /// 选中项的DataRow对象
      /// </summary>
      [Category("自定义"), Description("CurrentItem,选中项的DataRow对象"), Browsable(false)]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
      [McDisplayName("CurrentItem")]
      public DataRow CurrentItem
      {
          get
          {
              return this._CurrentItem;
          }
          protected set
          {
              this._CurrentItem = value;
          }
      }
      
      
      private DataSet _BillDataSet = new DataSet();
      /// <summary>
      /// 单据的数据源
      /// </summary>
      [Category("自定义"), Description("BillDataSet,单据的数据源"), Browsable(false)]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
      [McDisplayName("BillDataSet")]
      public DataSet BillDataSet
      {
          get
          {
              return this._BillDataSet;
          }
          set
          {
              this._BillDataSet = value;
          }
      }
      
      /// <summary>
      /// 没有多语言的情况下的默认显示标题
      /// </summary>
      [Category("多语言"), Description("DesigeCaption,没有多语言的情况下的默认显示标题"), Browsable(true)]
      [McDisplayName("DesigeCaption")]
      public override string DesigeCaption
      {
          get
          {
              return this.CaptionControl.Text.Trim();
          }
          set
          {
              this.CaptionControl.Text = value;
          }
      }

            也可以根据自己喜好(当然是符合客户习惯的),画蛇添足:

    private bool _IsNull = true;
      /// <summary>
      /// 可空性
      /// </summary>
      [Category("验证"), Description("IsNull,可空性"), Browsable(true)]
      [McDisplayName("IsNull")]
      public override bool IsNull
      {
          get
          {
              SetBackColor();
              return this._IsNull;
          }
          set
          {
              this._IsNull = value;
              SetBackColor();
          }
      }
      ...
        /// <summary>
        /// 设置背景色
        /// </summary>
        private void SetBackColor()
        {
            if (this.ValueControl.Properties.ReadOnly == true)
            {
                this.ValueControl.BackColor = Color.FromArgb(242, 242, 243);
            }
            else
            {
                if (this._IsNull.Equals(true) == false)
                {
                    this.ValueControl.BackColor = Color.Yellow;
                }
                else
                {
                    this.ValueControl.BackColor = this._TextBackColor;
                }
            }
        }

            当设置控件必填的时候,设置控件的背景色用于区分,具体效果如图:

            封装好控件取值,填充值的方法,以及控件数据源绑定的方法(具体根据自己实际项目应用为准,此处只是举个栗子)

    /// <summary>
    /// 取控件的值
    /// </summary>
    /// <return>Object</return>
    public override object GetValue()
    {
        DataRowView rowview = null;
        BindingSource bs = null;
        object v = null;
    
        v = this.ValueControl.EditValue == null || this.ValueControl.EditValue == DBNull.Value ? string.Empty : this.ValueControl.EditValue.ToString();
        return v;
    }
    
    /// <summary>
    /// 设置控件的值
    /// </summary>
    /// <param name="value">控件的值</param>
    /// <return>int</return>
    public override int SetValue(object value)
    {
        this.ValueControl.EditValue = value == null || value == DBNull.Value ? string.Empty : value;
        return 1;
    }
    
    
    /// <summary>
    /// 设置数据绑定
    /// </summary>
    /// <param name="binding">数据绑定对象</param>
    /// <return>int</return>
    public override int SetDataBinding(object binding)
    {
        this.BindingObject = this.ValueControl.DataBindings.Add("EditValue", binding, this.Field, true, DataSourceUpdateMode.OnValidation, string.Empty, this.FormatString);
        SetColumnDisplayFormat();
        if (binding is BindingSource)
        {
            int maxlength = 0;
            if (((BindingSource)binding).DataSource is DataView)
            {
                if (((DataView)(((BindingSource)binding).DataSource)).Table.Columns[this.Field].DataType == typeof(string))
                {
                    maxlength = ((DataView)(((BindingSource)binding).DataSource)).Table.Columns[this.Field].MaxLength;
                    if (maxlength >= 0)
                    {
                        this.MaxLength = maxlength;
                    }
                }
            }
            else if (((BindingSource)binding).DataSource is DataTable)
            {
                if (((DataTable)(((BindingSource)binding).DataSource)).Columns[this.Field].DataType == typeof(string))
                {
                    maxlength = ((DataTable)(((BindingSource)binding).DataSource)).Columns[this.Field].MaxLength;
                    if (maxlength >= 0)
                    {
                        this.MaxLength = maxlength;
                    }
                }
            }
        }
        return 1;
    }
    
    /// <summary>
    /// 设置下拉框的数据源
    /// </summary>
    /// <param name="binding">下拉框的数据源</param>
    /// <param name="displayMember">显示值字段名</param>
    /// <param name="valueMember">实际值字段名</param>
    /// <returns>int</returns>
    public override int SetSourceTableBinding(object binding, string displayMember, string valueMember)
    {
        this.DisplayMemberPath = displayMember;
        this.SelectedValuePath = valueMember;
        this.ValueControl.Properties.DataSource = binding;
        this._ResourceDataSource = binding;
        return 1;
    }

           完成!为测试效果,在窗体Load事件中造个测试数据,看看效果:

    DataTable dataTable = new DataTable("Student"); 
    dataTable.Columns.Add("编号", typeof(String));
    dataTable.Columns.Add("昵称", typeof(String));
    dataTable.Columns.Add("名称", typeof(String)); 
    dataTable.Rows.Add(new String[] { "1", "James", "张三" });
    dataTable.Rows.Add(new String[] { "2", "Mary", "李四" });
    dataTable.Rows.Add(new String[] { "3", "Jack", "王五" });
    dataTable.Rows.Add(new String[] { "4", "joy", "赵六" });
    dataTable.Rows.Add(new String[] { "5", "jay", "钱七"});
    dataTable.Rows.Add(new String[] { "6", "stephen", "康忠鑫"});
    
    kzxSearchCbbeSupperStar.SetSourceTableBinding(dataTable, "名称", "昵称");

           和原始Dev控件一样,支持筛选功能,妈妈再也不用担心客户反馈因数据量大的问题查找不便了!

    结束语

            由于后续所有重写/重绘控件都在同一个项目使用,而且Dev系统引用文件较多,压缩后源码文件仍然很大,如果有需要源码的朋友,可以微信公众号联系博主,源码可以免费赠予~!有疑问的也可以CALL我一起探讨。

            最后,感谢您的耐心陪伴!如果觉得本篇博文对您或者身边朋友有帮助的,麻烦点个关注!赠人玫瑰,手留余香,您的支持就是我写作最大的动力,感谢您的关注,期待和您一起探讨!再会!

  • 相关阅读:
    国外保健品品牌介绍
    海淘第一单
    表查询语句与方法
    表与表关系
    表完整性约束
    表字段数据类型
    存储引擎
    数据库之MySQL基本操作
    MAC重置MySQL root 密码
    进程池、线程池、协程
  • 原文地址:https://www.cnblogs.com/axing/p/12664139.html
Copyright © 2020-2023  润新知