现在的位置: 首页 > 综合 > 正文

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

2013年06月30日 ⁄ 综合 ⁄ 共 19759字 ⁄ 字号 评论关闭

一、效果图

 

 

实现功能:

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

抱歉!评论已关闭.