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

来源:互联网 发布:microservice node 编辑:程序博客网 时间:2024/04/30 08:23

一、效果图



实现功能:

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;

        

          }

原创粉丝点击