請求書を管理するための C# Windows フォーム アプリケーションの作成に取り組んでおり、正しい方向に進んでいるかどうかを確認するために支援が必要です。する必要がある:
- 編集可能なグリッドに SQL Server テーブル (請求書の数は異なります) から請求書のグループを表示します
- ウィンドウには、ユーザーが顧客データを入力できるテキストボックスが必要です。これにより、元のグリッド結果がユーザーのエントリに一致する行にフィルターされます。
- グリッドの上部に、現在グリッドに表示されているすべての行の一致するチェックボックス列を更新するためにユーザーがチェックできる追加のチェックボックスが必要です。フィルタが入力されている場合、チェック アクションは表示された行にのみ適用されます。
- ユーザーは変更をデータベースにコミットする前にいくつかの行のチェックを外す必要がある場合があるため、変更をデータベースにすぐにコミットしないでください。そのため、変更をコミット/保存するためのアクション ボタンも必要になります。
これを達成するにはおそらくを使用する必要があることはわかっていますが、DataGridView
何にバインドすればよいかわかりません。MSDN のこの記事は有望に見えBindingList
ますが、データベース テーブルからクラスを入力する方法がわかりません。この記事では Add メソッドを呼び出して個々の行を追加していますが、一度にすべての行を追加できるようにしたいと考えています (または、少なくとも数行のコードですべての行を追加するループが必要です)。
BindingList
私はそれがクラスで可能であると仮定します。また、クラスのプロパティとBindingList
同様に、クラスは行フィルタリングをサポートしていますか? このクラスを参照するStackOverflowに関する別の記事がありますが、データベースから を埋める方法、それにフィルターを適用する方法、または の行を実用的に変更する方法についての詳細は説明されていません。RowFilter
DataView
BindingList
DataGridView
MSDNの記事によると、変更は DGV 自体ではなく、基になるデータ ソースに対して行われ、INotifyPropertyChanged
インターフェイスを介して DGV が更新されるようです。何を演奏する必要があるかについては、ある程度のアイデアがあります。ピースを配置するのに少し助けが必要です。すべての助けに感謝します!
私はこれを理解し、助けが必要な他の人の例としてコードを以下に示します。これが最善の方法である場合とそうでない場合がありますが、私にとってはうまくいきました。
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 Insurance_Manager
{
public partial class InvoiceEditor : Form
{
private Boolean ignoreChange = false;
private Char type;
private DataTable invoices;
private SqlDataAdapter adapter;
#region Class Constructors
public InvoiceEditor(Char iType)
{
// Initialize window components
InitializeComponent();
type = iType;
}
#endregion
#region Class Methods
// This function calculates the grid totals
private void CalculateTotals()
{
// Initialize values
Double all = 0;
Double doNotPay = 0;
Double paid = 0;
Double wrongAmount = 0;
// Loop through each row in the displayable grid and total the rows
foreach (DataRowView viewRow in invoices.DefaultView)
{
DataRow row = viewRow.Row;
all += Double.Parse(row["Amount"].ToString());
if (Boolean.Parse(row["DoNotPay"].ToString()) == true) { doNotPay += Double.Parse(row["Amount"].ToString()); }
if (Boolean.Parse(row["Paid"].ToString()) == true) { paid += Double.Parse(row["Amount"].ToString()); }
if (Boolean.Parse(row["WrongAmount"].ToString()) == true) { wrongAmount += Double.Parse(row["Amount"].ToString()); }
}
// Set the totals to the textbox
tbAllTotal.Text = String.Format(all.ToString(), "{0:c}");
tbDoNotPayTotal.Text = String.Format(doNotPay.ToString(), "{0:c}");
tbPaidTotal.Text = String.Format(paid.ToString(), "{0:c}");
tbWrongAmtTotal.Text = String.Format(wrongAmount.ToString(), "{0:c}");
}
// This functions loads the invoices for the grid
private void LoadInvoices()
{
// Fill the data table
SqlConnection conn = new SqlConnection("Data Source=REPORTSERVER;Initial Catalog=Insurance;Integrated Security=True");
conn.Open();
String query = "";
query += "Select ";
query += " IsNull(C.CustomerName,'') CustomerName, ";
query += " IsNull(C.[Contract],'') [Contract], ";
query += " IsNull(Convert(VarChar(20),I.Receipt),'') Receipt, ";
query += " IsNull(I.PolicyNumber,'') PolicyNumber, ";
query += " IsNull(I.[Type],'') [Type], ";
query += " I.DateBilled, ";
query += " I.Amount, ";
query += " I.DatePaid, ";
query += " I.Paid, ";
query += " I.DoNotPay, ";
query += " I.WrongAmount, ";
query += " I.ID, ";
query += " IsNull(I.Notes,'') Notes ";
query += "From ";
query += " Invoice I ";
query += " Join Customer C On I.CustomerID = C.ID ";
switch (type)
{
case 'A':
query += "Where I.ID Is Not Null And I.CustomerID Is Not Null ";
break;
case 'C':
query += "Where I.CustomerID Is Null ";
break;
case 'N':
query += "Where I.DoNotPay = 1 And I.CustomerID Is Not Null ";
break;
case 'P':
query += "Where I.Paid = 1 And I.CustomerID Is Not Null ";
break;
case 'U':
query += "Where I.DoNotPay = 0 And I.Paid = 0 And I.CustomerID Is Not Null ";
break;
case 'W':
query += "Where I.WrongAmount = 1 And I.CustomerID Is Not Null ";
break;
}
query += "Order By ";
query += " I.DateBilled ";
adapter = new SqlDataAdapter(query, conn);
invoices = new DataTable();
adapter.Fill(invoices);
// Link the data table to the grid
dgvInvoices.DataSource = invoices;
dgvInvoices.Columns[0].DataPropertyName = "CustomerName";
dgvInvoices.Columns[0].ReadOnly = true;
dgvInvoices.Columns[1].DataPropertyName = "Contract";
dgvInvoices.Columns[1].ReadOnly = true;
dgvInvoices.Columns[2].DataPropertyName = "Receipt";
dgvInvoices.Columns[2].ReadOnly = true;
dgvInvoices.Columns[3].DataPropertyName = "PolicyNumber";
dgvInvoices.Columns[3].ReadOnly = true;
dgvInvoices.Columns[4].DataPropertyName = "PolicyNumber";
dgvInvoices.Columns[4].ReadOnly = true;
dgvInvoices.Columns[5].DataPropertyName = "DateBilled";
dgvInvoices.Columns[5].ReadOnly = true;
dgvInvoices.Columns[6].DataPropertyName = "Amount";
dgvInvoices.Columns[6].DefaultCellStyle.Format = "c";
dgvInvoices.Columns[7].DataPropertyName = "DatePaid";
dgvInvoices.Columns[8].DataPropertyName = "Paid";
dgvInvoices.Columns[9].DataPropertyName = "DoNotPay";
dgvInvoices.Columns[10].DataPropertyName = "WrongAmount";
dgvInvoices.Columns[11].DataPropertyName = "ID";
dgvInvoices.Columns[11].Visible = false;
dgvInvoices.Columns[12].DataPropertyName = "Notes";
dgvInvoices.Columns[12].Visible = false;
// Close the database connection
conn.Close();
// Calculate totals
CalculateTotals();
}
// This function resets all of the fields
private void ResetFields()
{
// Turn on the ignore change flag
ignoreChange = true;
// Reset actions
cbDoNotPay.Checked = false;
cbPaid.Checked = false;
cbWrongAmt.Checked = false;
// Reset filter fields
dpMinDateBilled.Text = "1/1/1900";
dpMaxDateBilled.Text = "12/31/2099";
dpMinDatePaid.Text = "1/1/1900";
dpMaxDatePaid.Text = "12/31/2099";
tbContract.Text = "";
tbName.Text = "";
tbPolicy.Text = "";
tbReceipt.Text = "";
// Turn off the ignore change flag
ignoreChange = false;
}
// This function saves the row to the database
private void Save(DataRow row)
{
// Format values as needed
Double amount = Double.Parse(row["Amount"].ToString());
Int32 receipt;
try
{
receipt = Int32.Parse(row["Receipt"].ToString());
}
catch
{
receipt = 0;
}
// Acquire a connection to the database
SqlConnection conn = new SqlConnection("Data Source=REPORTSERVER;Initial Catalog=Insurance;Integrated Security=True");
conn.Open();
// Save the customer to the database
SqlCommand cmd = new SqlCommand("usp_SaveInvoice", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@InvoiceID", SqlDbType.Int).Value = row["ID"];
if (receipt != 0)
{
cmd.Parameters.Add("@Receipt", SqlDbType.Int).Value = row["Receipt"];
}
else
{
cmd.Parameters.Add("@Receipt", SqlDbType.Int).Value = DBNull.Value;
}
cmd.Parameters.Add("@Type", SqlDbType.VarChar, 10).Value = row["Type"];
cmd.Parameters.Add("@Policy", SqlDbType.VarChar, 15).Value = row["PolicyNumber"];
cmd.Parameters.Add("@DateBilled", SqlDbType.Date).Value = DateTime.Parse(row["DateBilled"].ToString());
cmd.Parameters.Add("@Amount", SqlDbType.Money).Value = amount;
if (row["DatePaid"].ToString().Equals(""))
{
cmd.Parameters.Add("@DatePaid", SqlDbType.Date).Value = DBNull.Value;
}
else
{
cmd.Parameters.Add("@DatePaid", SqlDbType.Date).Value = DateTime.Parse(row["DatePaid"].ToString());
}
cmd.Parameters.Add("@Paid", SqlDbType.Bit).Value = row["Paid"];
cmd.Parameters.Add("@DoNotPay", SqlDbType.Bit).Value = row["DoNotPay"];
cmd.Parameters.Add("@WrongAmount", SqlDbType.Bit).Value = row["WrongAmount"];
cmd.Parameters.Add("@Notes", SqlDbType.VarChar, 200000000).Value = row["Notes"];
cmd.Parameters.Add("@UserName", SqlDbType.VarChar, 100).Value = Environment.UserName;
cmd.ExecuteNonQuery();
cmd.Dispose();
// Close the connection to the database
conn.Close();
conn.Dispose();
}
// This function goes through the rows and saves each one to the database
private Boolean SaveRows()
{
// Initialize the return variable
Boolean returnVal = true;
// Change the grid focus to end any edits so they are committed to the datatable
dgvInvoices.CurrentCell = null;
// Loop through each row in the data table and validate it
foreach (DataRow row in invoices.Rows)
{
if (returnVal == false)
{
continue;
}
else
{
// If the row has changed, validate changes
if (row.RowState == DataRowState.Modified)
{
returnVal = Validate(row);
}
}
}
// Loop through each row in the data table and save it
if (returnVal)
{
// Loop through each row in the data table
foreach (DataRow row in invoices.Rows)
{
// If the row has changed, save changes
if (row.RowState == DataRowState.Modified)
{
Save(row);
}
}
}
if (returnVal)
{
MessageBox.Show("Database updated!");
LoadInvoices();
}
// Return value
return returnVal;
}
// This function validates the data row to make sure it can be saved to the database
private Boolean Validate(DataRow row)
{
// Validate date received
DateTime dateBilled;
try
{
dateBilled = DateTime.Parse(row["DateBilled"].ToString());
}
catch
{
MessageBox.Show("Date received is incorrect");
return false;
}
if (dateBilled < DateTime.Parse("1/1/2010"))
{
MessageBox.Show("Date received must be on or after 1/1/2010");
return false;
}
// Validate date paid
DateTime datePaid;
if (!row["DatePaid"].ToString().Trim().Equals(""))
{
try
{
datePaid = DateTime.Parse(row["DatePaid"].ToString());
}
catch
{
MessageBox.Show("Date paid is incorrect");
return false;
}
if (datePaid < dateBilled)
{
MessageBox.Show("Date paid must be on or after date received");
return false;
}
}
// Validate amount
Double amount;
try
{
amount = Double.Parse(row["Amount"].ToString());
}
catch
{
MessageBox.Show("Amount is incorrect");
return false;
}
if (amount <= 0)
{
MessageBox.Show("Amount must be positive");
return false;
}
// Return true
return true;
}
#endregion
#region Window Events
// This function marks the column as checked
private void CheckColumn(String columnName, Boolean checkState)
{
// Turn on the ignore change flag to prevent recalculating totals for each row
ignoreChange = true;
// Loop through each row in the displayable grid
foreach (DataRowView viewRow in invoices.DefaultView)
{
DataRow row = viewRow.Row;
row[columnName] = checkState;
if ((columnName == "Paid") && (checkState == true))
{
row["DoNotPay"] = false;
}
if ((columnName == "DoNotPay") && (checkState == true))
{
row["Paid"] = false;
}
}
// Turn off the ignore change flag
ignoreChange = false;
// Recalculate the totals
CalculateTotals();
// Refresh the grid
dgvInvoices.Refresh();
}
// This function is used to limit the characters input in a date box
private void Date_KeyPress(object sender, KeyPressEventArgs e)
{
if (("/0123456789".Contains(e.KeyChar)) || ((Int32)e.KeyChar == 8))
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}
// This function is called when filters update
private void FilterTextChanged(object sender, EventArgs e)
{
// Build the filter
if (!ignoreChange)
{
String filter = "";
filter += "CustomerName Like '%" + tbName.Text.Replace("'", "''") + "%' ";
filter += "And [Contract] Like '%" + tbContract.Text.Replace("'", "''") + "%' ";
filter += "And PolicyNumber Like '%" + tbPolicy.Text.Replace("'", "''") + "%' ";
filter += "And Convert(Receipt,System.String) Like '%" + tbReceipt.Text.Replace("'", "''") + "%' ";
filter += "And IsNull(DateBilled,'1/1/1900') >= '" + dpMinDateBilled.Text + "' ";
filter += "And IsNull(DateBilled,'1/1/1900') <= '" + dpMaxDateBilled.Text + "' ";
filter += "And IsNull(DatePaid,'1/1/1900') >= '" + dpMinDatePaid.Text + "' ";
filter += "And IsNull(DatePaid,'1/1/1900') <= '" + dpMaxDatePaid.Text + "' ";
// Apply the filter to the table
invoices.DefaultView.RowFilter = filter;
// Calculate totals
CalculateTotals();
}
}
// This function is called when the form is closing
private void InvoiceEditor_FormClosing(object sender, FormClosingEventArgs e)
{
// By default, assume not closing
e.Cancel = false;
// Check if changes have been made
Boolean changed = false;
foreach (DataRow row in invoices.Rows)
{
if (changed)
{
continue;
}
else
{
if (row.RowState == DataRowState.Modified)
{
changed = true;
}
}
}
// If changes were made, ask the user if they want to save changes
if (changed == true)
{
// Ask the customer if they want to save changes
DialogResult choice = MessageBox.Show("Changes have been made to invoices. Do you want to save them?", "Save Changes", MessageBoxButtons.YesNoCancel);
if (choice == DialogResult.Yes)
{
e.Cancel = !SaveRows();
}
else if (choice == DialogResult.Cancel)
{
e.Cancel = true;
}
}
}
// This function is called when the form is loading
private void InvoiceEditor_Load(object sender, EventArgs e)
{
// Set the window fields to defaults
ResetFields();
// Load invoices
LoadInvoices();
// Set the window header
switch (type)
{
case 'A':
this.Text = "All Invoices";
break;
case 'C':
this.Text = "Invoices w/o Customers";
break;
case 'N':
this.Text = "Do Not Pay Invoices";
break;
case 'P':
this.Text = "Paid Invoices";
break;
case 'U':
this.Text = "Unpaid Invoices";
break;
case 'W':
this.Text = "Wrong Amount Invoices";
break;
}
}
// This function is called when the Do Not Pay flag is clicked
private void cbDoNotPay_CheckedChanged(object sender, EventArgs e)
{
// If the user checked the box, check all of the rows in the grid
if (!ignoreChange)
{
CheckColumn("DoNotPay", cbDoNotPay.Checked);
}
}
// This functions is called when the Paid flag is clicked
private void cbPaid_CheckedChanged(object sender, EventArgs e)
{
// If the user checked the box, check all of the rows in the grid
if (!ignoreChange)
{
CheckColumn("Paid", cbPaid.Checked);
}
}
// This function is called when the Wrong Amount flag is clicked
private void cbWrongAmt_CheckedChanged(object sender, EventArgs e)
{
// If the user checked the box, check all of the rows in the grid
if (!ignoreChange)
{
CheckColumn("WrongAmount", cbWrongAmt.Checked);
}
}
// This function is called when the cell value changes
private void dgvInvoices_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
// If one of the flag changes, recalculate the totals
if ((!ignoreChange) && (" 8 9 10 ".Contains(e.ColumnIndex.ToString())))
{
// Change focus to end the edit
dgvInvoices.CurrentCell = dgvInvoices.Rows[e.RowIndex].Cells[0];
// If the paid flag changes, flip the other one
if ((e.ColumnIndex == 8) && (Boolean.Parse(dgvInvoices.Rows[e.RowIndex].Cells[8].Value.ToString()) == true))
{
dgvInvoices.Rows[e.RowIndex].Cells[9].Value = false;
}
// If the do not pay flag changes, flip the other one
if ((e.ColumnIndex == 9) && (Boolean.Parse(dgvInvoices.Rows[e.RowIndex].Cells[9].Value.ToString()) == true))
{
dgvInvoices.Rows[e.RowIndex].Cells[8].Value = false;
}
dgvInvoices.Refresh();
CalculateTotals();
}
}
// This function is called when a row in grid is double clicked
private void dgvInvoices_DoubleClick(object sender, EventArgs e)
{
// Get the selected row
DataRowView row = (DataRowView)dgvInvoices.BindingContext[invoices].Current;
Int32 InvoiceID;
try
{
InvoiceID = Int32.Parse(row["ID"].ToString().Trim());
}
catch
{
InvoiceID = 0;
}
// Ensure a row was selected
if (InvoiceID != 0)
{
// Display the window for editing this invoice
Invoice inv = new Invoice(InvoiceID,row["CustomerName"].ToString());
inv.ShowDialog(this.MdiParent);
}
}
#endregion
#region Menu Items
// This function is called when the close button is clicked on the menu
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{
// Close the form
this.Close();
}
// This function is called when the save button is clicked on the menu
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
// Call the save method
SaveRows();
}
// This function is called when the undo button is clicked on the menu
private void undoToolStripMenuItem_Click(object sender, EventArgs e)
{
// Reset filters
ResetFields();
// Reload the grid
LoadInvoices();
}
#endregion
}
}