WPF使用DataGrid控件显示和更新ADO.NET数据源

来源:互联网 发布:电子密码编程 编辑:程序博客网 时间:2024/04/29 12:05

1. 显示

假设SQL Server服务器的名称为ExampleServer。数据库为ExampleDB,其中有一张数据表Book,表中有ID和Title两列,数据类型均为为nvarchar,ID为主键。MainWindow.xaml中的XAML代码为:

<DataGrid AutoGenerateColumns="False" Name="dataGrid1" CanUserAddRows="False">     <DataGrid.Columns>          <DataGridTextColumn Header="ID" Binding="{Binding ID}"/>          <DataGridTextColumn Header="Title" Binding="{Binding Title}"/>      </DataGrid.Columns></DataGrid>

将DataGrid的CanUserAddRows属性设为false,否则DataGrid显示时最下面一直会多一行。
访问SQL Server数据库的C#代码如下所示:

public class BookDatabase{// 连接字符串,使用集成安全性static const string ConnectionStr= "Data Source=ExampleServer,"+"Initial Catalog=ExampleDB,Integrated Security=true";// 得到数据源public static DataView GetDataView(){using (SqlConnection connection = new SqlConnection(ConnectionStr)){try{DataSet ds = new DataSet();connection.Open();SqlDataAdapter adapter = new SqlDataAdapter("select * from [ExampleDB].[dbo].[Book]", connection);adapter.Fill(ds, "Book");ds.Tables["Book"].RowChanged += new DataRowChangeEventHandler(ds_RowChanged);return ds.Tables["Book"].DefaultView;}catch(SqlException ex){MessageBox.Show(ex.Message);}return null;}}}                                       

设置DataGrid绑定数据的代码为:

dataGrid1.ItemsSource = BookDatabase.GetDataView();

DataGrid的绑定数据源是一个DataView对象,相应的,DataGrid中每一行对应着一个DataRowView对象。

2. 更新

DataGrid允许用户编辑,如果是DataGridTextColumn列,用户双击某个单元格(Cell)时,即可进入编辑模式,就像Excel中一样。由于在XAML中设置的binding的默认模式为双向绑定,即<Binding="{Binding ID, Mode=TwoDay}",DataRowView中的相应属性会更改,DataRowView对应的DataRow也会更改。用户编辑之后,DataRow的RowState会从Unchanged变成Modified,然后可以利用SqlDataAdapter将更改的DataRow解析回SQL Server数据库中,实现持久化。

可以增加一个Update button,并在其Click响应中调用下列BookDatabase.UpdateDatabase函数:

public class BookDatabase{public static void UpdateDatabase(DataTable table){try{SqlConnection connection = new SqlConnection(ConnectionStr);SqlDataAdapter adapter = new SqlDataAdapter("select * from [ExampleDB].[dbo].[Book]", connection);SqlCommandBuilder cb = new SqlCommandBuilder(adapter);cd.GetUpdateCommand();int count = adapter.Update(table);}catch(SqlException ex){MessageBox.Show(ex.Message);table.RejectChanges();}}}

button的Click响应(class MainWindow成员函数)为:

private void buttonUpdate_Click(object sender, RoutedEventArgs e)    {        if (dataGrid1.ItemsSource != null)        {            BookDatabase.UpdateDatabase((dataGrid1.ItemsSource as DataView).Table);        }    }

如果想在用户编辑之后立即更新,一个很自然的想法是在DataGrid的CellEditEnding的事件处理执行这一任务,但在这里不可能完成

在CellEditEnding的事件处理函数(此函数是class MainWindow的成员)中用下面的代码可以查看相应的DataRow的状态:

private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e){// DataRowView对应的DataRowDataRow r = ((DataRowView)dataGrid1.SelectedItem).Row;Console.WriteLine(Row[0].ToString());Console.WriteLine(Row.RowState.ToString());}

可以发现DataRow的属性已经改成了用户刚才编辑的新值,但是DataRow的RowState仍然是Unchanged,这就是不能在这个事件处理中更新数据库的原因。事实上用户编辑引发的事件顺序是这样的:

(1) DataGrid的BeginningEdit事件

(2) DataGrid的CellEditEnding事件

(3) DataRow的RowChanging事件

(4) DataRow的RowChanged事件

可以在第四个RowChanged的事件处理函数中实现立即更新数据库:

public class BookDatabase{static void ds_RowChanged(object sender, DataRowChangeEventArgs e){// 此例中只有修改的情况,应该输出Modified。// 若增加行或删除行,还可能为Added或Deleted等。Console.WriteLine(e.Row.RowState.ToString()); UpdateDatabase(e.Row.Table);}}