4.7.3. Showing the Invoice Lines

We have two choices for displaying the invoice lines:

  1. Getting data for each invoice from the INVOICE_LINE navigation property and displaying the contents of this complex property in the detail grid, probably with LINQ transformations

  2. Getting the data for each invoice with a separate LINQ query that will be re-executed when the cursor moves to another record in the master grid

Either way has its advantages and drawbacks.

The first one assumes that we want to retrieve all invoices at once for the specified period together with the bound data from the invoice lines when the invoice form is opened. Although it is done with one SQL query, it may take quite a while and requires a large amount of random-access memory. It is better suited to web applications where records are usually displayed page by page.

The second one is a bit more difficult to implement, but it allows the invoice form to be opened quickly and requires less resource. However, each time the cursor in the master grid moves, an SQL query will be executed, generating network traffic, albeit with only a small volume of data.

For our application we will use the second approach. We need an event handler for the BindingSource component for editing the current record:

  1. private void masterBinding_CurrentChanged(object sender, EventArgs e) {
  2. LoadInvoiceLineData(this.CurrentInvoice.Id);
  3. detailGridView.DataSource = detailBinding;
  4. }

Now, the method for loading the invoice data:

  1. private void LoadInvoiceLineData(int? id) {
  2. var dbContext = AppVariables.getDbContext();
  3. var lines =
  4. from line in dbContext.INVOICE_LINES
  5. where line.INVOICE_ID == id
  6. select new InvoiceLineView
  7. {
  8. Id = line.INVOICE_LINE_ID,
  9. Invoice_Id = line.INVOICE_ID,
  10. Product_Id = line.PRODUCT_ID,
  11. Product = line.PRODUCT.NAME,
  12. Quantity = line.QUANTITY,
  13. Price = line.SALE_PRICE,
  14. Total = Math.Round(line.QUANTITY * line.SALE_PRICE, 2)
  15. };
  16. detailBinding.DataSource = lines.ToBindingList();
  17. }

We use the InvoiceLineView class as an extension:

  1. public class InvoiceLineView {
  2. public int Id { get; set; }
  3. public int Invoice_Id { get; set; }
  4. public int Product_Id { get; set; }
  5. public string Product { get; set; }
  6. public decimal Quantity { get; set; }
  7. public decimal Price { get; set; }
  8. public decimal Total { get; set; }
  9. }

Unlike the InvoiceView class, this one has no method for loading one current record. In our example, the speed of reloading the detail grid it is not crucial, because one document does not contain thousands of items. Implementing this method is optional.

Now we will add a special property for retrieving the current line of the document selected in the detail grid.

  1. public InvoiceLineView CurrentInvoiceLine {
  2. get {
  3. return (InvoiceLineView)detailBinding.Current;
  4. }
  5. }