65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 DataGrid 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (56投票s)

2005 年 3 月 31 日

6分钟阅读

viewsIcon

798131

downloadIcon

27988

ADO.NET 控件使用介绍。

Sample Image

引言

这个用于 DataGrid 的小型应用程序允许用户

  • DataGrid 中添加新行。
  • 保存或更新 DataGrid 中的一行。
  • DataGrid 中删除现有行。
  • 从 XML 文件读取数据。
  • DataSet 的当前数据复制到 C:\ 根目录下的三个文件
    1. MyXMLText.txt (文本文件)
    2. MyXMLdata.xml (XML 文件)
    3. MyXMLschema.xsd (架构文件)
  • 将表的当前数据写入 C:\ 上的文本文件。

“DataGrid 应用程序”中的 DataGrid 控件绑定到单个 DataSet 对象。“DataGrid 应用程序”的 DataSet 对象最初使用 OleDbDataAdapter 对象从数据库填充。

什么是 DataGrid?

Windows 窗体 DataGrid 控件为 ADO.NET 数据集提供用户界面,以可滚动网格显示 ADO.NET 表格数据,并允许更新数据源。如果 DataGrid 绑定到包含单个表且没有关系的数据库,数据将以简单的行和列显示,就像电子表格一样。DataGrid 控件是 Windows 窗体中最有用和最灵活的控件之一。一旦 DataGrid 控件设置为有效数据源,控件就会自动填充,通过根据数据结构创建列和行。DataGrid 控件可以用于显示单个表或一组表之间的层次关系。

例如:如果您将 DataGrid 绑定到具有多个相关表的数据,并且启用了 DataGrid 上的导航,则 DataGrid 会在每一行中显示所谓的“展开器”。

通过展开器,您可以从父表导航到子表。如果您单击 DataGrid 中的节点,它会显示子表。如果您单击“后退”按钮,它会显示原始父表。以这种方式,网格显示表之间的层次关系。

请记住,DataGrid 中一次只能显示一个表。DataGrid 的有效数据源包括

  • DataTable
  • 数据视图
  • DataSet
  • DataViewManager
  • 一维数组
  • 任何实现 IListSource 接口的组件。

如何以编程方式在 DataGrid 中显示数据?

如果您想在 DataGrid 中显示数据,您需要定义一个 DataGrid 对象。当然,有不同的方法来填充 DataGrid 中的数据。例如

首先定义一个 DataGrid 并声明一个新的 DataGrid,然后设置 DataGrid 的一些属性(位置、名称、大小等)。

   private System.Windows.Forms.DataGrid dataGrid1;
   this.dataGrid1 = new System.Windows.Forms.DataGrid();
   this.dataGrid1.Location = new System.Drawing.Point(16, 40);
   this.dataGrid1.Name = "dataGrid1";
   this.dataGrid1.Size = new System.Drawing.Size(256, 176);

现在我们可以将所有必要的命令放入一个方法 "fnDisplayDataInDataGrid()" 中,以在 DataGrid 中显示数据。

private void fnDisplayDataInDataGrid()
{
   string conStr ="Integrated Security=SSPI;" +
   "Initial Catalog=Northwind;" +
   "Data Source=SONY\\MYSQLSERVER;";
   SqlConnection conn = new SqlConnection(conStr);
   // Open the connection
   conn.Open();
   // Create a data adapter object
   SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM MyTable", conn);
   // Create a DataSet object
   DataSet ds = new DataSet();
   // filling the DataSet 
   adapter.Fill(ds,"MyTable");
   // you can use one of the followings.Both works fine.
   // this.dataGrid1.SetDataBinding(ds,"MyTable"); or
   this.dataGrid1.DataSource=ds.DefaultViewManager;
}

此时,我将向您推荐我的上一篇文章(面向初学者的 ADO.NET 使用指南),您可以在其中找到更多关于 DataGrid 的有趣提示和技巧(即,如何捕获 DataGrid 中的按键事件 - 上、下、Esc 等)。

工作原理

连接到 MS Access 数据库后,所有记录都将显示在 DataGrid 上。

首次运行应用程序时,将调用方法 "fnRefresh()"。它清除 DataSet 的内容,填充 DataAdapter,并在 DataGrid 中显示数据源中的数据。之后,所有按钮都已准备好使用。以下是方法 "fnRefresh()" 的代码片段

private void fnRefresh() 
{
   this.dataSet11.Clear(); 
   this.oleDbDataAdapter1.Fill(this.dataSet11,"MyContactsTable"); 
   this.dataGrid1.DataSource=this.dataSet11.Tables["MyContactsTable"].DefaultView; 
}

插入新行

如果您单击“插入”按钮添加新记录,则 DataGrid 上的最后一行将被选中,并且之前单击的行将被取消选中。输入该行的数据后,单击“保存/更新”按钮保存新行。这是插入新行的方法

private void fnInsertNew() 
{
   //keep in mind the previous clicked row to unselect
   int iPrevRowindex=this.iRowIndex; 
   MessageBox.Show("Enter the new record at the end" + 
     " of the DataGrid and click 'Save/Update'-button", "Stop"); 
   this.btInsertnew.Enabled=false; 
   //get how many records in the table 
   this.iRowIndex=this.dataSet11.Tables["MyContactsTable"].Rows.Count; 
   //select the last row 
   this.dataGrid1.Select(this.iRowIndex);
   //unselect the previous row
   this.dataGrid1.UnSelect(iPrevRowindex);
}

保存或更新新/更改的行

方法 "fnSaveUpdate()" 的代码片段将 DataSet 中所做的更改保存回数据库。dataSet11 的 "GetChanges" 方法将返回一个新的 DataSet,名为 "myChangedDataset",其中包含所有已修改(更新、删除或插入)的行。如果未进行任何更改,则 "GetChanges" 方法返回一个 "null" DataSet

如果在更新数据库时发生任何类型的错误,OleDbDataAdapter 的 "Update" 方法将生成一个异常。此逻辑包含在 try/catch 块中。如果发生异常,您将收到一个消息框,通知您错误。然后调用 "RejectChanges" 方法以放弃您所做的更改。如果进行了任何更改,系统会告知用户受影响/更改的行数,并且 "AcceptChanges()" 方法将把所做的更改标记为 DataSet 中的永久更改。现在我们需要使用 "fnRefresh()" 方法调用刷新 DataSet。我认为这是更新数据库时一种“简单”而稳健的技术。

以下是“fnSaveUpdate()”方法的代码片段

private void fnSaveUpdate() 
{
   try 
   { 
      //put the modified DataSet into a new DataSet(myChangedDataset) 
      DataSet myChangedDataset= this.dataSet11.GetChanges(); 
      if (myChangedDataset != null) 
     { 
        //get how many rows changed 
        int modifiedRows = this.oleDbDataAdapter1.Update(myChangedDataset); 
        MessageBox.Show("Database has been updated successfully: " + 
                      modifiedRows + " Modified row(s) ", "Success"); 
        this.dataSet11.AcceptChanges(); //accept the all changes 
        fnRefresh(); 
     } 
     else 
     } 
        MessageBox.Show("Nothing to save", "No changes"); 
      }//if-else 
   } 
   catch(Exception ex) 
  { 
     //if something somehow went wrong 
    MessageBox.Show("An error occurred updating the database: " + 
      ex.Message, "Error",  MessageBoxButtons.OK, MessageBoxIcon.Error); 
    this.dataSet11.RejectChanges(); //cancel the changes 
  }//try-catch 
  fnEnableDisableAllButtons(true);
}

删除当前行

在删除行之前询问用户始终是一个好习惯。单击“是”后,DataGrid 上的当前行将被删除、更新和刷新。删除行的方法如下

private void fnDelete() 
{
    //ask user if wanting to delete
    DialogResult dr=MessageBox.Show("Are you sure you want to delete this row ? ", 
           "Confirm deleting",  MessageBoxButtons.YesNo, MessageBoxIcon.Question);
    if (dr ==DialogResult.Yes) 
    {
        DataTable tbl=new DataTable("MyContactsTable");
        tbl=this.dataSet11.Tables[0];
        int i=this.iRowIndex;//get the index of the row you clicked
        tbl.Rows[i].Delete(); //delete the row
        this.oleDbDataAdapter1.Update(tbl); //update the table
        this.fnRefresh(); //refresh the table 
    }
}

从 XML 文件读取数据

有时您必须从 XML 文件读取数据并将其显示在 DataGrid 中。为了做到这一点,我将 XML 文件传递给该方法;如果文件存在,我将清除 DataSet 并使用指定的文件将 XML 数据读入 DataSet。以下代码片段显示了这一点

private void fnDataReadingFromXMLFile(string filename)
{
  //check if the file exists
  if ( File.Exists(filename))
  {
    //clear the DataSet contents
    this.dataSet11.Clear();
    MessageBox.Show("Data reading from "+filename+" -file");
    this.dataSet11.ReadXml(filename);
   } //if
   else {
    MessageBox.Show(filename + " does NOT exist; Please click" + 
       " first the button 'CopyToXML' ", "File Error", 
       MessageBoxButtons.OK, MessageBoxIcon.Error );
  }//else
}

将 DataSet 复制到文本/XML/架构文件

单击“CopyToXML”按钮将调用“fnCopyToXMLandTextFile()”方法。正如您从其名称中可以猜到的,它将 DataSet 的当前数据写入 C:\ 根目录下的三个文件

  1. 文本文件:MyXMLdataText.txt
  2. XML 文件:XMLdata.xml
  3. 架构文件:MyXMLschema.xsd

如果您希望使用其他路径而不是“C:\”,则必须相应地更改代码。以下代码片段演示了此功能

private void fnCopyToXMLandTextFile() 
{
    if (this.dataSet11 == null) 
    {
        return; //cancel 
    }
    files. this.dataSet11.WriteXml("C:\\MyXMLText.txt"); 
    this.dataSet11.WriteXml("C:\\MyXMLdata.xml", XmlWriteMode.WriteSchema); 
    this.dataSet11.WriteXmlSchema("C:\\MyXMLschema.xsd"); 
    string s="The current data of the DataSet coppied on C:\\ as: \n"; 
    s +="* Text file: MyXMLdataText.txt\n"; 
    s +="* XML file: XMLdata.xml\n"; 
    s +="* Schema file: MyXMLschema.xsd"; 
    MessageBox.Show(s, "Copy to XML/Text/Schema file"); 
}

将表的当前数据写入硬盘(C:\)上的文本文件

因为 ExecuteReader 需要一个打开且可用的连接,所以我们首先必须打开数据库连接。如果连接的当前状态是 Closed,您会收到错误消息。打开连接后,我们创建 OleDbCommand 的实例、SQL 语句的 CommandTextOleDbDataReaderStreamWriter 的实例。然后,在 while 循环中,OleDbDataReader 读取数据行并将它们写入文本文件。最后,它关闭 OleDbDataReader。在 StreamWriter writer = new StreamWriter("C:\\MyTextFile.txt", false) 中,我们传递文本文件并将 bool 值设置为“false”。如果文件不存在,无论如何都会创建一个新的文本文件。如果文件存在并且第二个参数是“false”,则文件将被覆盖,因为是“false”。如果值为“true”,则文件不会被覆盖,数据将附加到文件中。以下是写入文本文件的代码片段

private void fnWriteToTextFile()
{
  OleDbDataReader reader;
  OleDbCommand cmd=new OleDbCommand();  
  this.oleDbConnection1.Open(); //open the connection
  cmd.CommandText="SELECT Address, City, Country, Email," + 
      " FirstName, LastName, Message, Phone FROM MyContactsTable";
  cmd.Connection=this.oleDbConnection1;
  reader=cmd.ExecuteReader();
 //the "using" statement causes the close method to be called internally.
 //if "using" not used, use "writer.Close()" in try-catch-finally explicitly
  using (StreamWriter writer = new StreamWriter("C:\\MyTextFile.txt",false)) 
  { 
  //false means: textfile is overwritten
  try
  {
    while (reader.Read())
    {
      writer.Write(reader["LastName"]);
      writer.Write("#"); //separator
      writer.Write(reader["FirstName"]);
      writer.Write("#");
      writer.Write(reader["Address"]);
      writer.Write("#");
      writer.Write(reader["City"]);
      writer.Write("#");
      writer.Write(reader["Country"]);
      writer.Write("#");
      writer.Write(reader["Email"]);
      writer.Write("#");
      writer.Write(reader["Message"]);
      writer.Write("#");
      writer.Write(reader["Phone"]);
      writer.WriteLine(); //next new line
    }//while 
  }catch (Exception excp) 
  {
    MessageBox.Show(excp.Message);
  }finally {
    reader.Close(); //close the OleDbDataReader
  }//try-catch-finally
 }//using
   MessageBox.Show("Data of table writtten into" + 
      " C:\\MyTextFile.txt file","Writing completed");
}

最后

我认为代码非常简单易懂,因为我尝试在几乎每行代码中都添加注释。希望您能在这里为您的项目找到一些有用的东西。一如既往,欢迎所有反馈。有关 DataGrid 的更多提示,请参阅我的另一篇文章链接:面向初学者的 ADO.NET 使用指南

祝您编码愉快!

© . All rights reserved.