本课将讨论ADO.NET中几个常用的脱机组件(如DataSet、DataTable等),以及如何在Windows窗体应用中的列表和DataGridView控件中绑定数据。首先,需要创建一个Windows窗体应用项目,打开Visual Studio Community 2017,通过菜单项“文件”>>“新建”>>“项目”,选择项目类型,如下图所示。

enter image description here

接下来,还需要通过菜单项“视图”>>“工具箱”打开工具箱栏,如下图所示。

enter image description here

在窗体中添加控件时,可以在工具箱栏中双击或拖拽到窗体,然后移动到指定的位置,下图中的窗体,共添加了一个按钮(Button)和一个文本框(TextBox)控件。

enter image description here

双击控件就可以打开默认的事件响应代码方法,如双击button1按钮,就可以看到如下代码段。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // button1控件的单击事件响应代码
        }
    }
}

还记得上一课中是如何连接数据库的吗?这里,我们在窗体中添加一个字段用于保存数据库连接字符串,并在窗体构造函数中初始化它,如下面的代码。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace WindowsFormsTest
{
    public partial class Form1 : Form
    {
        // 数据库连接字符串
        private string CnnStr;
        // 构造函数
        public Form1()
        {
            InitializeComponent();
            //
            // 初始化连接字符串
            SqlConnectionStringBuilder sb =
                new SqlConnectionStringBuilder();
            sb.DataSource = @".\MSSQLSERVER1";
            sb.InitialCatalog = @"Cdb_Test";
            sb.IntegratedSecurity = true;
            sb.AsynchronousProcessing = true;
            sb.Pooling = true;
            CnnStr = sb.ConnectionString;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 在这里添加测试代码
        }
    }
}

代码中,使用私有字段CnnStr保存数据库连接字符串,并在构造函数中对其进行赋值;另外,不要忘了引用System.Data.SqlClient命名空间。这里,只使用一个窗体进行测试,所以数据库连接字符串就定义在了窗体中,实际的项目开发中,数据库等资源可以创建一个公共的类进行有效的组织、管理和分配。

下面的代码会测试数据库的连接,并将结果显示在textBox1控件中。

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            using (SqlConnection cnn = new SqlConnection(CnnStr))
            {
                cnn.Open();
                textBox1.Text = "数据库连接成功";
            }
        }
        catch(Exception ex)
        {
            textBox1.Text = ex.Message;
        }
    }

这里,我将测试代码放在了button1按钮的单击事件中,按F5执行程序并单击button1按钮,如果数据库连接成功就会显示如下图所示的结果。

enter image description here

接下来主要讨论脱机组件的使用,如DataSet、DataTable等,并讨论如何将脱机组件的数据绑定到列表类控件和DataGridView控件中。下面,在Form1窗体中添加一个ListBox控件和一个DataGridView控件,如下图所示。

enter image description here

下面的代码,我们将UserMain表的内容显示到dataGridView1控件中。

    private void button1_Click(object sender, EventArgs e)
    {
        using (SqlConnection cnn = new SqlConnection(CnnStr))
        {
            cnn.Open();
            SqlCommand cmd = cnn.CreateCommand();
            cmd.CommandText = "select * from UserMain;";
            using (SqlDataAdapter ada = new SqlDataAdapter(cmd))
            {
                DataSet ds = new DataSet();
                ada.Fill(ds,"UserMain");
                // 数据绑定
                dataGridView1.DataSource = ds;
                dataGridView1.DataMember = "UserMain";
            }
        }
    }

本例及接下来的测试会省略异常捕捉代码,如果不能正确执行,可以根据抛出的异常信息进行调试。代码执行结果如下图所示。

enter image description here

本例中,我们使用SqlDataAdapter类的Fill()方法将查询的数据填充到DataSet对象中,此时,会在DataSet对象中生成一个表(DataTable类型),Fill()方法的第二个参数指定了表的名称。将DataSet中的数据绑定到DataGridView控件时,指定了DataGridView控件的两个属性,包括:

  • DataSource属性,指定数据源对象。
  • DataMember属性,指定数据源中的具体成员名称。

DataSet中的Tables属性包含了所有表的集合,可以使用表名或数值索引进行访问,如示例中的"UserMain"表,可以使用ds.Tables[0]或ds.Tables["UserMain"]进行访问;此外,指定DataGridView控件的数据源时,还可以直接使用表对象,此时就不需要指定DataMember属性了,如下面的代码。

dataGridView1.DataSource = ds.Tables["UserMain"];

将数据绑定到ListBox控件时,可以直接显示一项数据,也可以显示“键/值”对应的两个数据,如下面的代码,将UserName作为显示的文本,而UserID数据作为列表项的值。

    private void button1_Click(object sender, EventArgs e)
    {
        using (SqlConnection cnn = new SqlConnection(CnnStr))
        {
            cnn.Open();
            SqlCommand cmd = cnn.CreateCommand();
            cmd.CommandText = "select * from UserMain;";
            using (SqlDataAdapter ada = new SqlDataAdapter(cmd))
            {
                DataSet ds = new DataSet();
                ada.Fill(ds,"UserMain");
                // 数据绑定
                listBox1.DataSource = ds.Tables["UserMain"];
                listBox1.DisplayMember = "UserName";
                listBox1.ValueMember = "UserID";
            }
        }
    }

代码执行结果如下图所示。

enter image description here

下面,我们再添加一个Button控件,使用默认的button2作为名称,如下图所示。

enter image description here

双击打开button2控件的单击事件响应代码,并添加如下内容。

    private void button2_Click(object sender, EventArgs e)
    {
        if (listBox1.SelectedIndex == -1)
        {
            textBox1.Text = "没有选择列表项";
        }
        else
        {
            textBox1.Text = string.Format("{0} : {1}",
                listBox1.SelectedValue, listBox1.Text);
        }
    }

执行程序,先单击button1绑定列表数据,然后就可以通过单击button2按钮显示选择项目的数值和文本了,如下图所示。

enter image description here

下面的代码会通过读取DataTable对象中的数据,将UserName字段的数据显示在listBox1控件中。

    private void button1_Click(object sender, EventArgs e)
    {
        using (SqlConnection cnn = new SqlConnection(CnnStr))
        {
            cnn.Open();
            SqlCommand cmd = cnn.CreateCommand();
            cmd.CommandText = "select * from UserMain;";
            using (SqlDataAdapter ada = new SqlDataAdapter(cmd))
            {
                DataSet ds = new DataSet();
                ada.Fill(ds,"UserMain");
                // 读取DataTable数据
                DataTable tbl = ds.Tables[0];
                for(int row=0;row<tbl.Rows.Count;row++)
                {
                    listBox1.Items.Add(tbl.Rows[row]["UserName"]);
                }
            }
        }
    }

DataTable对象中,Rows属性表示所有行(数据记录)的集合,而Columns属性表示所有列(字段信息)的集合,如下面的代码,将在listBox1列表中显示所有的字段名。

    private void button1_Click(object sender, EventArgs e)
    {
        using (SqlConnection cnn = new SqlConnection(CnnStr))
        {
            cnn.Open();
            SqlCommand cmd = cnn.CreateCommand();
            cmd.CommandText = "select * from UserMain;";
            using (SqlDataAdapter ada = new SqlDataAdapter(cmd))
            {
                DataSet ds = new DataSet();
                ada.Fill(ds,"UserMain");
                // 读取DataTable数据
                DataTable tbl = ds.Tables[0];
                for(int col=0;col<tbl.Columns.Count;col++)
                {
                    listBox1.Items.Add(tbl.Columns[col].ColumnName);
                }
            }
        }
    }

代码执行结果如下图所示。

enter image description here

无论是Windows窗体应用、或者是Web窗体应用,合理地使用数据绑定功能,可以提高应用的开发效率;如果有需要,还可以创建自己的数据处理组件,大家可以在学习和工作不断探索和尝试。

CHY软件小屋原创作品!