DataGrid使用技巧(二)

       DataGrid使用技巧(二)

------------如何实现多行表头

       有时候听有些朋友抱怨.NET的DataGrid不是很好用。就我个人的体会,DataGrid的功能非常强大,可以使我们随心所欲的完成各种各样的工作,可惜就是实现起来不够简单明了。我对平时经常碰到的一些问题积累了一些解决的方法,现在把它们总结一下供大家参考。
       比较经常碰到的一个问题是:我们希望DataGrid的表头是多行的(图1)。我在网上找了很久也找不到解决的方法,后来想到了DataGrid的CaptionText和CaptionFont属性。于是我就想能不能在Caption的显示区域画出多行表头。下面的示例代码实现了这个想法,结果如图1所示。

       首先需要编写一个类来表示自画的表头,这个类将记录表头的显示文本、图标和属于它管辖的列的信息。

                  //表头类
                  public class TopHeaderColumn
                  {
                         public TopHeaderColumn()
                         {
                         this.columnCollection=new ArrayList();
                         }
                          private string caption;
                        //表头的显示文本 
                          public string Caption
                          {
                            get {return caption;}
                            set {caption=value;}
                          }
                         private ArrayList columnCollection;
                        //用来记录属于表头管辖的各列的信息(通过往集合里添加object)
                         public ArrayList ColumnCollection
                         {
                          get {return this.columnCollection;}
                          set {this.columnCollection=value;}
                          }
                         private int width;
                         //表头的宽度
                         public int Width
                         {
                          get {return width;}
                          set {width=value;}
                          }
                         private Image image=null;
                         //表头的图标
                         public Image Image
                         {
                           get {return image;}
                           set {image=value;}
                          }

                    }
       另外,因为以后的代码需要DataGrid水平滚动条的位置,而DataGrid无法取得水平滚动条的位置,所以需要对DataGrid做一点修改。
                   public class myDataGrid:DataGrid
                   {
  
                       public ScrollBar HScrollBar
                       {
                          get {return this.HorizScrollBar;}
                       }
                   }

       好了,可以工作了。新建一个Window应用程序,加入一个myDataGrid、SqlConnection和ImageList,连接SQL数据库NorthWind。当然,还得加入上面的代码
                  
               namespace WindowsApplication1
              {
                       public class Form1 : System.Windows.Forms.Form
                       {
                          private System.Data.SqlClient.SqlConnection sqlConnection1;
                          private myDataGrid dataGrid1;
                          private ArrayList al;
                          private System.Windows.Forms.ImageList imageList1;
                          //在InitializeComponent()里加入这一句:this.dataGrid1 = new myDataGrid(),并根据你的需要设置其他的DataGrid属性。注意,CaptionVisible必须设为true,CaptionText=""。
                          private void Form1_Load(object sender, System.EventArgs e)
                          {
                             SqlDataAdapter da=new SqlDataAdapter("select lastname, firstname, Address,City from employees",this.sqlConnection1);
                             DataSet ds=new DataSet();
                             da.Fill(ds,"employees");
                             this.dataGrid1.DataSource=ds;
                             this.dataGrid1.DataMember="employees";

                             //设置DataGrid的各列
                             DataGridTextBoxColumn c1=new DataGridTextBoxColumn();
                             DataGridTextBoxColumn c2=new DataGridTextBoxColumn();
                             DataGridTextBoxColumn c3=new DataGridTextBoxColumn();
                             DataGridTextBoxColumn c4=new DataGridTextBoxColumn();
                             c1.MappingName="lastname";
                             c2.MappingName="firstname";
                             c3.MappingName="Address";
                             c4.MappingName="City";
                             c1.HeaderText="lastname";
                             c2.HeaderText="firstname";
                             c3.HeaderText="Address";
                             c4.HeaderText="City";
               c1.WidthChanged+=new EventHandler(this.abc);//列的宽变动时调整表头宽度
                             c2.WidthChanged+=new EventHandler(this.abc);
                             c3.WidthChanged+=new EventHandler(this.abc);
                             c4.WidthChanged+=new EventHandler(this.abc);

                             DataGridTableStyle dts=new DataGridTableStyle();
                             dts.GridColumnStyles.Add(c1);
                             dts.GridColumnStyles.Add(c2);
                             dts.GridColumnStyles.Add(c3);
                             dts.GridColumnStyles.Add(c4);

                             dts.MappingName="employees";   this.dataGrid1.TableStyles.Add(dts);

                              //建立自画的表头类并将它们加入集合al   
                             al=new ArrayList();
                             TopHeaderColumn tc1=new TopHeaderColumn();
                             tc1.Caption="Name";
                             tc1.Image=this.imageList1.Images[0];
                             tc1.ColumnCollection.Add(0);//记录它管辖的列的index
                             tc1.ColumnCollection.Add(1);
                             tc1.Width=c1.Width+c2.Width;

                            TopHeaderColumn tc2=new TopHeaderColumn();
                             tc2.Caption="Address";
                             tc2.ColumnCollection.Add(2);
                             tc2.ColumnCollection.Add(3);
                             tc2.Width=c3.Width+c4.Width;
   
                             al.Add(tc1);
                             al.Add(tc2);
                             this.dataGrid1.Paint += new System.Windows.Forms.PaintEventHandler(this.dataGrid1_Paint);
                          }

                         private void dataGrid1_Paint(object sender, System.Windows.Forms. PaintEventArgs e)
                        {
                           int x=0;
                           //计算出第一个表头的左边距
                           int left=this.dataGrid1.TableStyles[0].RowHeaderWidth-this.dataGrid1.HScrollBar.Value;
                           //遍历表头集合al,画出表头   
                           foreach (object o in this.al)
                           {
                          //计算出表头文字(文字居中)的左边距
                           x=left+(((TopHeaderColumn)o).Width-Convert.ToInt32(e.Graphics. MeasureString (((TopHeaderColumn)o).Caption, this.dataGrid1.CaptionFont). Width))/2;
                          //完成表头绘制  
                          if (((TopHeaderColumn)o).Image!=null)
                          e.Graphics.DrawImage(((TopHeaderColumn)o).Image,x-imageList1.Images[0].Size.Width,0); 

                           e.Graphics.DrawString(((TopHeaderColumn)o).Caption,this.dataGrid1. CaptionFont,new SolidBrush(this.dataGrid1.CaptionForeColor),x,0);
                           if (x>0)
                           e.Graphics.DrawLine(new Pen(Color.Black,2),left-1,0,left-1,this.dataGrid1.Height);
                           //计算出下一个表头的左边距
                           left+=((TopHeaderColumn)o).Width;
                           }
                           if (x                           e.Graphics.DrawLine(new Pen(Color.Black,2),left-1,0,left-1,this.dataGrid1.Height);  
                         }

                     private void abc(object sender,EventArgs e)
                     {
                       //设置表头的宽度
                        foreach (object o in this.al)
                        {
                         ((TopHeaderColumn)o).Width=0;
                        foreach (int i in ((TopHeaderColumn)o).ColumnCollection)
                        {   ((TopHeaderColumn)o).Width+=this.dataGrid1.TableStyles[0].GridColumnStyles[i].Width;
                        }
                        }
                      }

                     private void dataGrid1_Scroll(object sender, System.EventArgs e)
                     {
                       this.dataGrid1.Refresh();
                     }

      上面的代码实现了两层表头,至于三层表头也同理。

      关于如何实现DataGrid多层表头,许多网友都提到,目前好像没有一种特别好的方便的方法。如果那位网友发现了更好的方法,请给我留一条短训告知,谢谢。

你可能感兴趣的:(datagrid,imagelist,object,dataset,image,c)