• dotNet 桌面程序改造计划.下拉框篇.DataGrid下拉窗口


    一、效果图

    实现功能:

    n         码名转换[输入编码焦点离开后显示名称]。

    n         下拉出带有DataGrid 的选取窗口。

    n         背景窗口不失去焦点

    二、        开发背景

    看到N 多程序里都有这种类是功能、如PB 的下拉数据窗口、Delphi 也有同类的Grid
    而 DotNet 的Grid 控件却没有这种功能、两个字“郁闷”、配合上一文中的一些经验和知识
    很轻易的就可以搞出 类是的功能、在发文档回报csdn 的各位同僚、数行代码寥表我心

    如果要转载文章情通知本人
    QQ:65323574 Email:FlashElf@163.com

    三、程序实现代码解析

    说明:本文使用的 SystemShell 和 NoActForm 类在上一篇文章
    “dotNet 桌面程序改造计划.下拉框篇.类似Word的颜色下拉框”中以有讲解这里不再重复。


           地址:http://blog.csdn.net/flashelf/archive/2005/01/30/273954.aspx

    3.1 DataGridVNTextColumnStyle 类

    本文的最基础类[具有 码、名 转换功能]


    using System;

    using System.Collections;

    using System.ComponentModel;

    using System.Drawing;

    using System.Windows.Forms;

    using System.Data;

    using System.Diagnostics;


    namespace MagicLink.FlashElf.Windows.Controls.WinDataGrid.ColumnStyle

    {

         /// <summary>

         /// 以[码|名]方式显示的 DataGridColumnStyle

         /// 如:

         /// 输入 1 显示 男

         /// 输入 2 显示 女

         /// </summary>

         public class DataGridVNTextColumnStyle:DataGridTextBoxColumn

         {

             /// <summary>

             /// (1)控件像绑定的数据对象 提交数据是使用的 delegate

             /// </summary>

             public delegate void DelegateCommit(

                  object ActData,

                  string TextBoxText,

                  ref bool Abort);


             /// <summary>

             ///(2)控件向绑定的数据对象提交数据时发生

             /// </summary>

             public event DelegateCommit DataCommit;

             private string _DisplayMember;

             private string _ValueMember;

             private DataView _dv;

             private DataTable _dt;

             private bool isEdit=false;

             private bool isCommit = false;

            

             public DataGridVNTextColumnStyle():base()

             {

                  //映射基类中的 TextBox 的key KeyPress 用于获得编辑状态

                  base.TextBox.KeyPress+=new KeyPressEventHandler(TextBox_KeyPress);


                  base.Disposed+=new EventHandler(DataGridVNTextColumnStyle_Disposed);

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

             }

             /// <summary>

             /// 基类 TextBox KeyPress

             /// </summary>

             /// <param name="sender"></param>

             /// <param name="e"></param>

             private void TextBox_KeyPress(object sender, KeyPressEventArgs e)

             {

                  //Debug.WriteLine("TextBox_KeyPress");

                  isEdit=true;

             }


             /// <summary>

             /// 显示的数据列

             /// </summary>

             public string DisplayMember

             {

                  get

                  {

                       return _DisplayMember;

                  }

                  set

                  {

                       _DisplayMember =value;

                  }

             }

             /// <summary>

             /// 实现[码|名] 方式显示的数据

             /// </summary>

             public DataTable DataSource

             {

                  get

                  {

                       return _dt;

                  }

                  set

                  {

                       if (_dt==null)

                       {

                           _dt =value;


                           _dv= new DataView();

                           _dv.Table=_dt;

                       }

                  }

             }

             /// <summary>

             /// 写入的数据列

             /// </summary>

             public string ValueMember

             {

                  get

                  {

                       return _ValueMember;

                  }

                  set

                  {

                       _ValueMember=value;

                  }

             }


             /// <summary>

             ///(3) 重写基类 Commit

             /// </summary>

             /// <param name="dataSource"></param>

             /// <param name="rowNum"></param>

             /// <returns></returns>

             protected  override bool Commit(CurrencyManager dataSource, int rowNum)

             {

                  //如果不是在编辑状态[这里代表用户没有在 textBox 输入数据时]

                  if (!isEdit) return base.Commit(dataSource, rowNum);

                  //如果上一个 Commit 没处理完

                  if (isCommit) return false;

                  try

                  {

                       isCommit=true;

                       //通过 GetColumnValueAtRow 取得当前单元格数据

                       object ActData = GetColumnValueAtRow(dataSource,rowNum);

                       //当前 TextBox 中的数据

                       string TextBoxText = TextBox.Text;

                       bool isAbort=false;

                       if (DataCommit!=null)

                       {

                           try

                           {

                                //触发事件[这样使使用本类时容易控制用户的输入]


                                //事件中可以使用异常 使 DataGrid 停止提交并弹出提示

                                DataCommit(ActData,TextBoxText,ref isAbort);

                           }

                           catch(Exception ex)

                           {

                          

                                throw ex;

                           }

                       }

                      

                       if (isAbort)

                       {

                           Abort(rowNum);

                           return false;

                 

                       }

                 

                       _dv.Sort= _ValueMember;

                       int index= 0;


                       try

                       {

                      

                           if ( TextBox.Text!="" && TextBox.Text!=NullText )

                           {

                                object oDate = TextBox.Text;

                                //判断数据在 DataView 中的第己行 如果不存在返回 -1

                                index = _dv.Find(oDate);

                           }

                           else

                           {

                                //如果是空的就设置为 DBNull

                                base.SetColumnValueAtRow(dataSource,rowNum,System.DBNull.Value);

                           }

                 

                                                           

                       }

                       catch(FormatException Fex)

                       {

                           Fex.GetHashCode();

                           //输入的不是期待的类型

                           index=-1;

                       }

                       catch(Exception ex)

                       {

                           //其他异常

                           throw ex;

                       }

                 

                       if (index < 0)

                       {

                          

                           //如果不是期待的数据

                           throw new ApplicationException("输入了不正确的数据!");

                       };

                 

                       try

                       {

                           return base.Commit(dataSource, rowNum);

                       }

                       catch(Exception ex)

                       {

                           throw ex;

                       }

                  }

                  finally

                  {

                       //还原开关变量

                       isCommit=false;

                       isEdit =false;

                  }

             }

                  /// <summary>

             /// (4)费编辑状态 绘制图像或文本到 Grid 的单元格中

             /// 重写本函数为了实现 [名称] 的显示

             /// </summary>

             /// <param name="g"></param>

             /// <param name="bounds"></param>

             /// <param name="source"></param>

             /// <param name="rowNum"></param>

             /// <param name="backBrush"></param>

             /// <param name="foreBrush"></param>

             /// <param name="alignToRight"></param>

             protected override void Paint(

                  Graphics g,

                  Rectangle bounds,

                  CurrencyManager source,

                  int rowNum,

                  Brush backBrush,

                  Brush foreBrush,

                  bool alignToRight)

             {

                 

                  object sDate=GetColumnValueAtRow(source, rowNum);

                  if (System.Convert.IsDBNull(sDate))

                  {

                       //如果数据是空 调用基类的绘制函数

            

                       base.Paint (g, bounds, source, rowNum,backBrush,foreBrush,alignToRight);

                  }

                  else

                  {

                       //sDate = DBNull.Value;

                       _dv.Sort= _ValueMember;

                       int index = _dv.Find(sDate);


                       //判断是否是期待的数据

                       if (index != -1)

                           sDate = _dv[index][_DisplayMember];

                       else

                           sDate = DBNull.Value;


                       Rectangle rect = bounds;

                       g.FillRectangle(backBrush,rect);


                       rect.Offset(0, 2);

                       rect.Height -= 2;

                       StringFormat Sf =new StringFormat();

                      

                       if (alignToRight)

                       Sf.Alignment=StringAlignment.Far;


                      

                       g.DrawString(sDate.ToString(),

                           this.TextBox.Font,

                           foreBrush, rect,Sf);

                       Sf.Dispose();


                  }       

                 


             }

             protected override void Paint(Graphics g,

                  Rectangle bounds,

                  CurrencyManager source,

                  int rowNum)

             {

                  Paint(g, bounds, source, rowNum, false);

             }

             protected override void Paint(

                  Graphics g,

                  Rectangle bounds,

                  CurrencyManager source,

                  int rowNum,

                  bool alignToRight)

             {

                  Paint(

                       g,bounds,

                       source,

                       rowNum,

                       Brushes.Red,

                       Brushes.Blue,

                       alignToRight);

             }


             private void DataGridVNTextColumnStyle_Disposed(object sender, EventArgs e)

             {

                  if (_dv!=null)

                  {

                       _dv.Dispose();

                  }

             }

         }

    }


     

    3.2 DataGridVNButtonColumnStyle 类

    继承 上一个 DataGridVNTextColumnStyle 多加了一个 button


    using System;

    using System.Collections;

    using System.ComponentModel;

    using System.Drawing;

    using System.Windows.Forms;


    namespace MagicLink.FlashElf.Windows.Controls.WinDataGrid.ColumnStyle

    {

         /// <summary>

         ///继承 DataGridVNTextColumnStyle 并在右面加入一个 button

         ///为了以后扩展用

         /// </summary>

         public class DataGridVNButtonColumnStyle:DataGridVNTextColumnStyle

         {

             protected System.Windows.Forms.ImageList _imageList;

             private System.ComponentModel.IContainer components;

             protected System.Windows.Forms.Button _button;


             private void InitializeComponent()

             {

                 

                  this.components = new System.ComponentModel.Container();

                  System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(DataGridVNButtonColumnStyle));

                  this._button = new System.Windows.Forms.Button();

                  this._imageList = new System.Windows.Forms.ImageList(this.components);

                  //

                  // _button

                  //

                  this._button.BackColor = System.Drawing.SystemColors.ActiveCaptionText;

                  this._button.FlatStyle = System.Windows.Forms.FlatStyle.Flat;

                  this._button.ImageIndex = 0;

                  this._button.ImageList = this._imageList;

                  this._button.Location = new System.Drawing.Point(0, 0);

                  this._button.Name = "_button";

                  this._button.TabIndex = 0;

                  //

                  // _imageList

                  //

                  this._imageList.ImageSize = new System.Drawing.Size(16, 16);

                  this._imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("_imageList.ImageStream")));

                  this._imageList.TransparentColor = System.Drawing.Color.Transparent;


             }

        

             public DataGridVNButtonColumnStyle():base()

             {

                  InitializeComponent();

                  base.Disposed+=new EventHandler(DataGridVNButtonColumnStyle_Disposed);

                  _button.Dock=DockStyle.Right;

                  _button.Size=new Size(16,16);

                  base.TextBox.Controls.Add(_button);

                 

                  _button.GotFocus+=new EventHandler(_button_GotFocus);

                  _button.Visible=true;

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

             }

             /// <summary>

             /// 如果鼠标点击 使 TextBox 获得焦点

             /// </summary>

             /// <param name="sender"></param>

             /// <param name="e"></param>

             private void _button_GotFocus(object sender, EventArgs e)

             {

                  _button.Parent.Focus();

             }

             public Button @Button

             {

                  get

                  {

                       return _button;

                  }

                 

             }


             private void DataGridVNButtonColumnStyle_Disposed(object sender, EventArgs e)

             {

                  if (_button!=null)

                  {

                       _button.Dispose();

                  }

                  if(_imageList!=null)

                  {

                       _imageList.Dispose();

                  }

             }

         }

    }


    3.2 DataGridVMShowGridColumnStyle 类

    实现下拉 DataGrid


    using System;

    using System.Collections;

    using System.ComponentModel;

    using System.Drawing;

    using System.Windows.Forms;

    using System.Data;

    using System.Diagnostics;


    namespace MagicLink.FlashElf.Windows.Controls.WinDataGrid.ColumnStyle

    {

         /// <summary>

         /// 以[码|名]方式显示带下拉

         /// DataGrid 列表的 DataGridColumnStyle

         /// </summary>

         public class DataGridVMShowGridColumnStyle:DataGridVNButtonColumnStyle

         {

            

             DataView _dv=new DataView();

             /// <summary>

             /// 下拉的窗口 上面就一个DataGrid

             /// </summary>

             GridForm _gf = new GridForm();

             private CurrencyManager _mc;

             private int _Rownum;


             public DataGridVMShowGridColumnStyle():base()

             {

            

                  //映射一些事件

                  base.Button.Click+=new EventHandler(_button_Click);

                  _gf.MouseDown+=new MouseEventHandler(Gf_MouseDown);

                  _gf.MouseMove+=new MouseEventHandler(Gf_MouseMove);

                  this.Disposed+=new EventHandler(DataGridVMShowGridColumnStyle_Disposed);

             }


             //(1)重写基类 edit 得到 CurrencyManager,rowNum

             /// <summary>

             /// 重写基类 edit

             /// </summary>

             /// <param name="source"></param>

             /// <param name="rowNum"></param>

             /// <param name="bounds"></param>

             /// <param name="readOnly"></param>

             /// <param name="instantText"></param>

             /// <param name="cellIsVisible"></param>

             protected  override void Edit(CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)

             {


                  _mc=source;

                  _Rownum = rowNum;

                  base.Edit (source, rowNum, bounds, readOnly, instantText, cellIsVisible);

             }


             /// <summary>

             /// 鼠标单机按钮 show 出大有 DataGrid 的窗口

             /// </summary>

             /// <param name="sender"></param>

             /// <param name="e"></param>

             private void _button_Click(object sender, EventArgs e)

             {

                  if (_dv.Table ==null)

                  {   

                       _dv.Table = base.DataSource;

                       _gf.dataGrid1.DataSource=_dv;

                       _dv.Sort = ValueMember;

                  }


                  if (_gf.Owner==null)

                  {

                       _gf.Owner = this._button.TopLevelControl as Form;

                  }

                  //调用 NoActForm 的 show

                  _gf.Show(TextBox);

                  //捕获鼠标

                  _gf.Capture=true;

                  //得到当前行在DataView里的位置

                  int selectIndex = _dv.Find(GetColumnValueAtRow(_mc,_Rownum));

                 

                  if (selectIndex==-1) selectIndex =0;


                  //不只到如何清除 DataGrid 的多选 就这么写了

                  for(int i = 0 ;i< _gf.dataGrid1.VisibleRowCount;i++)

                  {

                       _gf.dataGrid1.UnSelect(i);

                  }

                  //选择 TextBox 里面的编码对应show出来的 DataGrid里的 行

                  _gf.dataGrid1.Select(selectIndex);

                  _gf.BindingContext[_dv].Position=selectIndex;


                 

             }


             /// <summary>

             /// 下拉窗口的 MouseMove 捕捉鼠标所以可以取到

             /// </summary>

             /// <param name="sender"></param>

             /// <param name="e"></param>

             private void Gf_MouseMove(object sender, MouseEventArgs e)

             {

                  DataGrid Grid = _gf.dataGrid1;

                  System.Windows.Forms.DataGrid.HitTestInfo hti;

                  //通过坐标取得 HitTestInfo 对象

                  hti = Grid.HitTest(e.X, e.Y);

                  //如果鼠标的位置在 单元格 或 行表头上

                  if (hti.Type == System.Windows.Forms.DataGrid.HitTestType.Cell ||

                       hti.Type == System.Windows.Forms.DataGrid.HitTestType.RowHeader)

                  {

                       int index = hti.Row;

                 

                 

                       if (index==-1 )index=0;


                       //不只到如何清除 DataGrid 的多选 就这么写了

                       for(int i = 0 ;i< Grid.VisibleRowCount;i++)

                       {

                           Grid.UnSelect(i);

                       }

                      

                       _gf.BindingContext[_dv].Position=index;

                       //选择鼠标下的行

                       Grid.Select(index);

                  }

                 

            

             }

             /// <summary>

             /// 下拉窗口鼠标按下

             /// </summary>

             /// <param name="sender"></param>

             /// <param name="e"></param>

             private void Gf_MouseDown(object sender, MouseEventArgs e)

             {

                  _gf.Capture=false;

                 

                  Point pt = Control.MousePosition;

                  //如果是在下拉窗口 窗口范围内

                  if(!(pt.X> _gf.Right || pt.X < _gf.Left|| pt.Y>_gf.Bottom || pt.Y< _gf.Top))

                  {

                       System.Windows.Forms.DataGrid.HitTestInfo hti;

                       hti = _gf.dataGrid1.HitTest(e.X, e.Y);

                       //鼠标下的行

                       int index = hti.Row;

                       //如果没有就当第一行处理

                       if (index==-1 )index=0;

                 

                       object oDate = _dv[index][base.ValueMember];

                 

                       object oldDate = base.GetColumnValueAtRow(_mc,_Rownum);

                       //如果下拉窗口选择的数据行和和原始数据不同

                       if (!oldDate.Equals(oDate))

                       {

                           //设置当前单元格数据

                           SetColumnValueAtRow(_mc,_Rownum,oDate);


                           ColumnStartedEditing(base.TextBox);


                           TextBox.Text=oDate.ToString();

                      

                       }

                      

                      

                  }

                  //隐藏下拉窗口

                  _gf.Hide();

            

                 


             }


            

             /// <summary>

             /// 清理战场

             /// </summary>

             /// <param name="sender"></param>

             /// <param name="e"></param>

             private void DataGridVMShowGridColumnStyle_Disposed(object sender, EventArgs e)

             {

                  if (_dv!=null)

                  {

                       _dv.Dispose();

                  }


                  if(_gf!=null)

                  {

                       _gf.Dispose();

                  }

             }

         }

    }

    3.2 如何使用

    和一般的 DataGridColumnStyle 查不多


    private void Form1_Load(object sender, System.EventArgs e)

             {

                  //准备 DataGrid 的数据

                  _dv.Table  = GetMainTable();

                  //准备下拉窗口的数据

                  DataTable SexDt =GetShowGridTable();

                 

                  DataGridTableStyle gts;

                  gts=new DataGridTableStyle();


                  DataGridVMShowGridColumnStyle Glc= new DataGridVMShowGridColumnStyle();

                               

                 

                  gts.MappingName=_dv.Table.TableName;


                  Glc.HeaderText="性别";

                  Glc.MappingName ="Sex";


                  Glc.DataSource = SexDt;

                  Glc.DisplayMember="Txt";

                  Glc.ValueMember="Id";


                  gts.GridColumnStyles.Add(Glc);

                 

                  dataGrid1.TableStyles.Add(gts);


                  //添加一个一般的列

                  DataGridColumnStyle dgcolStyle;

                  dgcolStyle= new DataGridTextBoxColumn();

                  dgcolStyle.MappingName ="id";

                  dgcolStyle.HeaderText = "编号";

                  gts.GridColumnStyles.Add(dgcolStyle);


                  Glc.DataCommit+=new DataGridVNTextColumnStyle.DelegateCommit(Glc_DataCommit);


                  dataGrid1.DataSource=_dv;


             }


             private void Glc_DataCommit(object ActData, string TextBoxText, ref bool Abort)

             {

                  //如果认为数据不符合要求 Abort = true 即可

                  Console.WriteLine("1:::{0},{1},{2}",ActData,TextBoxText,Abort);


             }

             private DataTable GetMainTable()

             {

                  DataTable dt =new DataTable("Test");

                  dt.Columns.Add("id",typeof(int));             

                  dt.Columns.Add("birthday",typeof(DateTime));

                  dt.Columns.Add("Sex",typeof(int));

                 

                  dt.Rows.Add(new object[]{1,DateTime.Now,1});

                 

                  return dt;


             }

             private DataTable GetShowGridTable()

             {

                  DataTable SexDt =new DataTable("SexTable");

                  SexDt.Columns.Add("Id",typeof(int));

                  SexDt.Columns.Add("Txt",typeof(String));

                  SexDt.Rows.Add(new object[]{1,"男"});

                  SexDt.Rows.Add(new object[]{2,"女"});


                  return SexDt;

            

              }


     


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/FlashElf/archive/2005/02/02/277121.aspx

  • 相关阅读:
    Android vector标签 PathData 画图超详解
    Echarts 出现不明竖线解决方案
    关于华为手机Log.d打印不出来log的问题
    Java源码解读(一)——HashMap
    算法小题
    Python简单小程序练习
    TCP/IP协议栈(三)——linux 向下的报文处理
    TCP协议(二)——TIME_WAIT状态
    Linux文件系统inode、block解释权限(三)
    Linux 基本权限(一)
  • 原文地址:https://www.cnblogs.com/chenbg2001/p/1913896.html
Copyright © 2020-2023  润新知