Reputation: 8245
For the purposes of invoicing, I'm keeping track of timesheet entries that are associated with an invoice by storing the selected timesheets in the browser Session and adding/removing entries to that list as the user updates:
The GridView loads all timesheets for the selected company and then indicates by changing row style and select button text:
private void HighlightInvoiceTimesheets()
{
var timesheets = Session["invoiceTimesheets"] as List<Timesheet>;
var invoiceTotalHours = 0;
foreach (var timesheet in timesheets)
{
var tid = timesheet.Id.ToString();
foreach (GridViewRow row in ItemsGrid.Rows)
{
var btn = row.Cells[ItemsGrid.Columns.Count - 1].Controls[0] as LinkButton;
if (ItemsGrid.DataKeys[row.RowIndex].Values["Id"].ToString() == tid)
{
row.CssClass = "success";
btn.Text = "Remove";
int.TryParse(row.Cells[5].Text, out int timesheetHours);
invoiceTotalHours += timesheetHours;
}
}
}
Session["invoiceTotalHours"] = invoiceTotalHours;
BillableHoursLabel.Text = invoiceTotalHours.ToString();
}
When the user "selects" an item in the GridView, it adds or removes the item from the collection in the Session and updates the GridView accordingly:
protected void ItemsGrid_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
// Get the list of timesheets associated with the invoice.
var list = (Session["invoiceTimesheets"] == null) ? new List<Timesheet>() : Session["invoiceTimesheets"] as List<Timesheet>;
// Get the selected timesheet.
int.TryParse(ItemsGrid.DataKeys[e.NewSelectedIndex].Values["Id"].ToString(), out int timesheetId);
var timesheet = timesheetService.GetClearTimesheet(timesheetId);
// Get the select button to update its text.
var btn = ItemsGrid.Rows[e.NewSelectedIndex].Cells[ItemsGrid.Columns.Count - 1].Controls[0] as LinkButton;
// Get the total hours billable for the invoice based on the total hours of the timesheets.
var invoiceTotalHours = (Session["invoiceTotalHours"] == null) ? 0 : int.Parse(Session["invoiceTotalHours"].ToString());
if (list.Find(x => x.Id == timesheetId) != null)
{
// The list contains the selected item, remove it and indicate removed.
list.Remove(timesheet);
ItemsGrid.Rows[e.NewSelectedIndex].CssClass = "";
btn.Text = "Select";
int.TryParse(Session["invoiceTotalHours"].ToString(), out invoiceTotalHours);
invoiceTotalHours -= timesheet.BillableHours;
}
else
{
// The list doesn't contain the selected item, add it and indicate added.
list.Add(timesheet);
ItemsGrid.Rows[e.NewSelectedIndex].CssClass = "success";
btn.Text = "Remove";
int.TryParse(Session["invoiceTotalHours"].ToString(), out invoiceTotalHours);
invoiceTotalHours += timesheet.BillableHours;
}
BillableHoursLabel.Text = invoiceTotalHours.ToString();
// Update the collection in the session.
Session["invoiceTimesheets"] = list;
}
This works without any errors but I'm very confused why list.Remove(timesheet);
doesn't actually update the list in memory.
As a result of this, the collection in the session doesn't get updated and changes made don't reflect on the database.
Upvotes: 1
Views: 146
Reputation: 110
It's because the timesheet you're trying to remove isn't the same object as the one you get from
var timesheet = timesheetService.GetClearTimesheet(timesheetId);
instead of this:
if (list.Find(x => x.Id == timesheetId) != null)
{
// The list contains the selected item, remove it and indicate removed.
list.Remove(timesheet);
Do this:
var timeSheetSession=list.FirstOrDefault(x => x.Id == timesheetId);
if(timeSheetSession!=null) list.Remove(timeSheetSession);
it's pseudo code, i didn't test it.
Upvotes: 2