C# 2010 Express で開発されたプログラムがあり、その下に個々のセル編集フィールドを持つ DataGridView で構成されるフォームがあります。行を選択 (左端をクリック) すると、その行の値が編集フィールドにコピーされます。変更が行われ、トランザクションの記憶ボタンがクリックされます。新しい値が DataGridView に表示されます。その後、フォームを閉じて再度開く (破棄して再読み込みする) と、新しい値ではなく、元の値が表示されます。明らかに、データベース レコードは更新されていません。
上記のプロセスが繰り返される場合、フォームを閉じる前にレコードが再度選択され、トランザクションの記憶ボタンが再度クリックされる場合を除いて、値はデータベースに保存されます。フォームを閉じてから再度開くと、新しい値が表示されます。
明らかに、望ましい動作は、[トランザクションの記憶] ボタンを最初にクリックした直後に値がデータベースに格納されることです。
次の宣言は、フォーム クラスの先頭に表示されます。
DataTable _dt;
SqlDataAdapter _adapter;
メソッド load_DataGridView() は次のようになります。アダプターの Update、Delete、および Insert クエリは、SqlCommandBuilder のそれぞれの GetXXXCommand() メソッドの呼び出しで構築されることに注意してください。デバッグ中のブレークポイントは、これらが正しく取り込まれたことを示します。
private void load_dataGridView()
{
DataTable dt = new DataTable();
_dt = dt;
SqlConnection dbconn = new SqlConnection(dbq.connectionString);
dbconn.Open();
string qstr = @"SELECT transaction_id
, 0 as pay
, m.has_splits
, m.Num
, m.Type
, m.last_date
, m.next_date
, m.Payee
, m.Memo
, m.Tax_Category
, m.Amount
, m.Clr
, m.Initials
, m.sales_tax_paid
, m.from_institution_id as FromInstitutionID
, m.from_institution as FromInstitution
, m.from_account_id as FromAccountID
, m.from_account as FromAccount
, m.from_envelope_id as FromEnvelopeID
, m.from_envelope as FromEnvelope
, m.to_institution_id as ToInstitutionID
, m.to_institution as ToInstitution
, m.to_account_id as ToAccountID
, m.to_account as ToAccount
, m.to_envelope_id as ToEnvelopeID
, m.to_envelope as ToEnvelope
, m.frequency
FROM memorized m
";
SqlDataAdapter adapter = new SqlDataAdapter(qstr,dbconn);
SqlCommandBuilder scb = new SqlCommandBuilder(adapter);
adapter.UpdateCommand = new SqlCommandBuilder(adapter).GetUpdateCommand();
adapter.DeleteCommand = new SqlCommandBuilder(adapter).GetDeleteCommand();
adapter.InsertCommand = new SqlCommandBuilder(adapter).GetInsertCommand();
_adapter = adapter;
_adapter.Fill(_dt);
build_dgv_columns(Properties.Settings.Default.currentInstitutionId,
Properties.Settings.Default.currentAccountId);
memorizedDataGridView.DataSource = _dt;
}
[トランザクションの記憶] ボタンがクリックされたときに呼び出されるコードは次のとおりです。
private void bnMemorizeTx_Click(object sender, EventArgs e)
{
if (_newTx)
{
_currentTxRow = _dt.Rows.Count;
_dt.Rows.Add();
_newTx = false;
}
else
{
_currentTxRow = memorizedDataGridView.SelectedRows[0].Index;
}
populateRowFromFields(memorizedDataGridView.Rows[_currentTxRow]);
memorizedDataGridView.Refresh();
memorizedDataGridView.ClearSelection();
//grid shows new value with no rows selected at this point, row is "dirty"
try
{
_adapter.Update(_dt);
}
catch (SqlException e1)
{
MessageBox.Show(e1.Message + e1.InnerException, "Error Thrown",MessageBoxButtons.OK);
}
reset_transaction_fields();
}
例外はスローされません。DataGridView から編集フィールドにデータを引き出してから再度書き戻すというアクションは、行が変更されたことを検出する _adapter.Update(_dt) コマンドの機能をどうにかしてサルにしているのではないかと思われます。何も更新しません。次に、2 回目の試行で、行が新たに選択された (新しい値が表示された) が、編集の変更が行われていない場合、機能します。どういうわけか、新しい値がグリッドに表示されていても、変更がコミットされていないようで、それを行うには行を再選択する必要があります。
以下の populateRowFromFields メソッドは、セル インデックスの列名参照を使用して、編集フィールドの値を行のセル値に書き戻します。
private void populateRowFromFields(DataGridViewRow dgvr)
{
dgvr.Cells["Num"].Value = tbRefNum.Text;
dgvr.Cells["Type"].Value = cbType.GetItemText(cbType.SelectedItem);
dgvr.Cells["last_date"].Value = dtpLastPaid.Value.ToShortDateString();
dgvr.Cells["next_date"].Value = dtpNextPay.Value.ToShortDateString();
dgvr.Cells["Payee"].Value = tbPayee.Text;
dgvr.Cells["Amount"].Value = tbAmount.Text;
dgvr.Cells["FromInstitutionID"].Value = cbFromInst.GetItemText(cbFromInst.SelectedValue); // fromInst
dgvr.Cells["FromInstitution"].Value = cbFromInst.GetItemText(cbFromInst.SelectedItem); // fromAcct
dgvr.Cells["FromAccountID"].Value = cbFromAcct.GetItemText(cbFromAcct.SelectedValue); // fromEnv
dgvr.Cells["FromAccount"].Value = cbFromAcct.GetItemText(cbFromAcct.SelectedItem); // fromInst
dgvr.Cells["FromEnvelopeID"].Value = cbFromEnv.GetItemText(cbFromEnv.SelectedValue); // fromAcct
dgvr.Cells["FromEnvelope"].Value = cbFromEnv.GetItemText(cbFromEnv.SelectedItem); // fromEnv
if ((cbType.GetItemText(cbType.SelectedItem) == "+iTx") || (cbType.GetItemText(cbType.SelectedItem) == "-iTx") || (cbType.GetItemText(cbType.SelectedItem) == "+eTx") || (cbType.GetItemText(cbType.SelectedItem) == "-eTx"))
{
dgvr.Cells["ToInstitutionID"].Value = cbToInst.GetItemText(cbToInst.SelectedValue); // toInst
dgvr.Cells["ToInstitution"].Value = cbToInst.GetItemText(cbToInst.SelectedItem); // toInst
dgvr.Cells["ToAccountID"].Value = cbToAcct.GetItemText(cbToAcct.SelectedValue); // toAcct
dgvr.Cells["ToAccount"].Value = cbToAcct.GetItemText(cbToAcct.SelectedItem); // toAcct
dgvr.Cells["ToEnvelopeID"].Value = cbToEnv.GetItemText(cbToEnv.SelectedValue); // toEnv
dgvr.Cells["ToEnvelope"].Value = cbToEnv.GetItemText(cbToEnv.SelectedItem); // toEnv
hideTxToFields();
}
dgvr.Cells["Memo"].Value = tbMemo.Text;
dgvr.Cells["Tax_Category"].Value = cbTaxCategory.GetItemText(cbTaxCategory.SelectedItem); // taxCategory
dgvr.Cells["sales_tax_paid"].Value = cbSalesTaxPaid.GetItemText(cbSalesTaxPaid.SelectedItem); // salesTaxPaid
dgvr.Cells["Clr"].Value = "U";
dgvr.Cells["Initials"].Value = cbBy.GetItemText(cbBy.SelectedItem); // by
dgvr.Cells["frequency"].Value = cbFrequency.GetItemText(cbFrequency.SelectedItem); // frequency
}
ヘルプ!これは私を夢中にさせています!