I am having problem with GridView on row command and stack up the data in another GridView:
private List<DistributionStandardPackingUnitItems> tempDistSPUI
{
get
{
if (ViewState["tempDistSPUI"] == null)
{
return new List<DistributionStandardPackingUnitItems>();
}
else
{
return (List<DistributionStandardPackingUnitItems>)ViewState["tempDistSPUI"];
}
}
set
{
ViewState["tempDistSPUI"] = value;
}
}
protected void gvSPU_OnRowCommand(object sender, GridViewCommandEventArgs e)
{
int packagesNeeded = prodPackBLL.getPackagesNeededByDistributionID(distributionID);
//Get selected standard packing name
int rowNo = int.Parse(e.CommandArgument.ToString());
SPUname = this.gvSPU.DataKeys[rowNo].Value.ToString();
lblSPUname.Text = SPUname;
//Get the record from view state
itemList = tempDistSPUI;
itemList = packBLL.getAllDistSPUItemByDistributionIDnSPUName(distributionID, SPUname);
gvFinalised.DataSource = itemList;
gvFinalised.DataBind();
//Save the last record to view state
this.tempDistSPUI = itemList;
}
Let's say when I first selected a row from gvSPU, it returns an itemList filled with data and display in gvFinalised. What I am trying to do is if I selected another row from gvSPU, the previous records in gvFinalised will still there and stack up another itemList from the secondly selected row instead of wiping up the record previously and display the latest itemList data.
I am using viewState but it does not work.
EDIT
protected void lbnAdd_Click(object sender, EventArgs e)
{
List<DistributionStandardPackingUnitItems> prodVariantDetail = new List<DistributionStandardPackingUnitItems>();
int packagesNeeded = prodPackBLL.getPackagesNeededByDistributionID(distributionID);
// get the last product variant IDs from ViewState
prodVariantIDList = this.SelectedVariantDetailIDs;
foreach (RepeaterItem ri in Repeater1.Items)
{
GridView gvProduct = (GridView)ri.FindControl("gvProduct");
foreach (GridViewRow gr in gvProduct.Rows)
{
CheckBox cb = (CheckBox)gr.FindControl("cbCheckRow");
//Prevent gvFinalised to store duplicate products
if (cb.Checked && !prodVariantIDList.Any(i => i == gvProduct.DataKeys[gr.RowIndex].Value.ToString()))
{
// add the corresponding DataKey to idList
prodVariantIDList.Add(gvProduct.DataKeys[gr.RowIndex].Value.ToString());
}
}
}
for (int i = 0; i < prodVariantIDList.Count; i++)
{
prodVariantDetail.Add(packBLL.getProdVariantDetailByID(prodVariantIDList[i]));
}
//Check if itemList and prodVariantDetail list contains any duplicate records
var Gdupes = itemList.GroupBy(x => new { x.id }).Where(x => x.Skip(1).Any()).ToList();
List<DistributionStandardPackingUnitItems> dupes = Gdupes.SelectMany(x => x).ToList();
prodVariantDetail = itemList.Except(dupes).ToList();
gvFinalised.DataSource = prodVariantDetail;
gvFinalised.DataBind();
foreach (GridViewRow gr in gvFinalised.Rows)
{
//Get the product packaging quantity by productName
string name = gr.Cells[1].Text;
int productQuantity = packBLL.getProductQuantityByName(name, distributionID);
TextBox tb = (TextBox)gr.Cells[5].FindControl("tbQuantity");
if (productQuantity == 0)
{
tb.Text = productQuantity.ToString();
}
else
{
tb.Text = (productQuantity / packagesNeeded).ToString();
}
}
// save prodVariantIDList to ViewState
this.SelectedVariantDetailIDs = prodVariantIDList;
}
private List<string> SelectedVariantDetailIDs
{
get
{
if (ViewState["SelectedVariantDetailIDs"] == null)
{
return new List<string>();
}
else
{
return (List<string>)ViewState["SelectedVariantDetailIDs"];
}
}
set
{
ViewState["SelectedVariantDetailIDs"] = value;
}
}
The problem is the following lines:
//Get the record from view state
itemList = tempDistSPUI;
// here itemList will be replaced
itemList = packBLL.getAllDistSPUItemByDistributionIDnSPUName(distributionID, SPUname);
First you assign tempDistSPUI from ViewState to itemList, but then you replace itemList at the next line. You need to add the elements returned from packBLL.getAllDistSPUItemByDistributionIDnSPUName to itemList instead of replacing itemList. Here's what I would do using List.AddRange Method:
itemList = tempDistSPUI;
// add the returned elements to itemList
itemList.AddRange(packBLL.getAllDistSPUItemByDistributionIDnSPUName(distributionID, SPUname));
UPDATE
To prevent duplication with the previous elements:
itemList = tempDistSPUI;
List<DistributionStandardPackingUnitItems> itemListNew = new List<DistributionStandardPackingUnitItems>();
itemListNew = packBLL.getAllDistSPUItemByDistributionIDnSPUName(distributionID, SPUname);
// get all previous IDs in a List<int>
List<int> previousIDs = itemList.Select(x => x.id).ToList();
// filter itemListNew and add the elements to itemList
itemList.AddRange(itemListNew.Where(x => !previousIDs.Contains(x.id));
Related
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.
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.
I have this table structure
patients:
PK_Patient
PatientID
PatientName
items:
PK_Item
ItemID
ItemDesc
enrolleditems:
PK_EnrollMeds
FK_User_Add
DateTimeAdded
FK_Item
I have a form which has the user included on the form, and datagridview which displays the items enrolled to patient (binded to enrolleditems but items datamember is only displayed on grid), then add and delete button.
The entry on the screenshot is manually added on the database ([MED0001] enrolleditems table) for sample purposes.
On the add button will open another forms which will load all the items and a checkbox to select which item to be added, then a select button which copy the selected datarows to datatable.
I have the below code for the Add button on Enroll Medication form
M3dEntities m3d = new M3dEntities();
enrollmeds _enrollmeds = new enrollmeds();
EnrollMedSelectionFrm enrollselectfrm;
public DataTable SelectedItems { get; set; }
private void AddBtn_Click(object sender, EventArgs e)
{
enrollselectfrm = new EnrollMedSelectionFrm();
var pxdetails = (from adm in m3d.admission
join pxDC in m3d.datacenter
on adm.FK_DC_Patient equals pxDC.PK_Datacenter
where adm.admissionNo == SelectedAdmNo
select new
{
adm,
pxDC
}).FirstOrDefault();
if (enrollselectfrm.ShowDialog() == DialogResult.OK)
{
if (SelectedItems == null)
{
enrollmedsBindingSource.Clear();
}
else
{
enrollmedsBindingSource.Clear();
foreach (DataRow dr in SelectedItems.Rows)
{
_enrollmeds = new enrollmeds();
_enrollmeds.items = new items();
_enrollmeds.FK_DC_Patient = pxdetails.pxDC.PK_Datacenter;
_enrollmeds.FK_DC_userAdd = mainfrm.PK_DC_UserLoggedIn;
var svrDT = ((IObjectContextAdapter)m3d).ObjectContext.CreateQuery<DateTime>("CurrentDateTime() ");
DateTime currdatetime = svrDT.AsEnumerable().First();
_enrollmeds.AddDateTime = currdatetime;
_enrollmeds.FK_Admission = pxdetails.adm.PK_Admission;
int pkItems = int.Parse(dr.Field<string>("PK_Items").ToString());
var itemdtls = (from i in m3d.items
where i.PK_Items == pkItems
select i).FirstOrDefault();
_enrollmeds.FK_Items = pkItems;
_enrollmeds.items.ItemID = itemdtls.ItemID;
_enrollmeds.items.ItemDesc = itemdtls.ItemDesc;
_enrollmeds.items.GenericName = itemdtls.GenericName;
_enrollmeds.items.ItemGroup = itemdtls.ItemGroup;
enrollmedsBindingSource.Add(_enrollmeds);
}
}
}
}
My problem with this is only the first selected item on the itemselection form.
I want to display all the items selected on the itemselection form to the enrollmedsDataGridView of enrollmedicines form.
Thank You in advance..
I'm currently working on my shopping cart. and I'm wondering how I can add drop down list column for quantity in every item that is inside the Cart. And also I want the limit of drop down list to be the number of the product stock. Hoping for a brief explanation. Thank you. :)
Cart.aspx.cs
protected void theCart()
{
var dt = new DataTable();
double totalPrice = 0;
dt.Columns.Add("product_name");
dt.Columns.Add("product_price");
dt.Columns.Add("product_stock");
List<ShoppingCartModel> shoppingList = (List<ShoppingCartModel>)Session["memberCart"];
if (shoppingList != null)
{
foreach (var item in shoppingList)
{
dt.Rows.Add(item.ProductName, item.Price, item.ProductStock);
totalPrice += item.Price;
}
}
lbl_total.Text = totalPrice.ToString();
MyGridView.DataSource = dt;
MyGridView.DataBind();
}
WebShop.aspx.cs
protected void pro_tbl_ItemCommand(object source, DataListCommandEventArgs e)
{
if (e.CommandName == "addtocart")
{
List<ShoppingCartModel> shoppingList = (List<ShoppingCartModel>)Session["memberCart"];
if (shoppingList == null)
{
shoppingList = new List<ShoppingCartModel>();
}
ShoppingCartModel shoppingModel = new ShoppingCartModel();
shoppingModel.ProductId = ((HiddenField)e.Item.FindControl("lblProductId")).Value;
shoppingModel.ProductName = ((Label)e.Item.FindControl("lbl_pname")).Text;
shoppingModel.ProductDescription = ((Label)e.Item.FindControl("lbl_pdesc")).Text;
shoppingModel.ProductStock = Convert.ToInt32(((Label)e.Item.FindControl("lbl_pstock")).Text);
shoppingModel.Price = Convert.ToDouble(((Label)e.Item.FindControl("lbl_price")).Text);
shoppingList.Add(shoppingModel);
Session["memberCart"] = shoppingList;
lbl_result.Text = "Product has been added to the cart";
}
}
I want to remove a selected item in my combobox
I have here a code upon form load, I am filling list items on combobox from database.
private void LoadComboField()
{
//string test = "<ROOT><DATA FieldGroup=\"PAYMENT_VIEW4\" FieldDescription=\"PNAME\" Output=\"1\" Filter=\"1\" FieldName=\"PATIENTNAME\" DataType=\"STRING\"/><DATA FieldGroup=\"PAYMENT_VIEW4\" FieldDescription=\"MEMID\" Output=\"1\" Filter=\"1\" FieldName=\"MEMBERID\" DataType=\"STRING\"/></ROOT>";
ReadXMLData(XMLDOC, dsCombo);
// ReadXMLData(test, dsCombo);
dt = dsCombo.Tables[0];
DataView dv1 = new DataView(dsCombo.Tables[0]);
this.cmbField.Items.Clear();
this.cmbField.DataSource = dv1;
this.cmbField.DisplayMember = "FieldDescription";
this.cmbField.ValueMember = "FieldName";
}
Then I have this code on SelectedValueChanged
private void cmbField_SelectedValueChanged(object sender, EventArgs e)
{
DataGridViewRow GridRowLoc = this.dgvFilter.CurrentRow;
AddGrid(iRowIdx);
int iRowCount = this.dgvFilter.RowCount - 1;
//this.dgvFilter.CurrentRow.IsNewRow
//if (GridRowLoc.IsNewRow) continue;
// MessageBox.Show(this.dgvFilter.RowCount.ToString());
if (this.cmbField.Text != "System.Data.DataRowView")
{
this.dgvFilter.Rows[iRowIdx].Cells["ColumnFieldName"].Value = this.cmbField.Text;
this.dgvFilter.Rows[iRowIdx].Cells["FieldName"].Value = this.cmbField.SelectedValue;
if (iRowCount <= iRowIdx)
{
DataRow drow = dttable.NewRow();
drow["ColumnNames"] = this.cmbField.Text;
drow["FieldName"]= this.cmbField.SelectedValue;
drow["Alias"]=string.Empty;
drow["DataType"]=string.Empty;
drow["Outputs"]=false;
drow["SortType"]=string.Empty;
drow["SortOrder"]=string.Empty;
drow["GroupBy"]=string.Empty;
drow["Filter"]=string.Empty;
drow["Or1"]=string.Empty;
drow["Or2"]=string.Empty;
drow["Or3"]=string.Empty;
drow["Or4"]=string.Empty;
drow["Or5"]=string.Empty;
drow["Or6"]=string.Empty;
drow["Or7"]=string.Empty;
drow["Or8"]=string.Empty;
drow["Or9"]=string.Empty;
drow["Or10"]=string.Empty;
dttable.Rows.Add(drow);
}
else
{
int irow = 0;
foreach (DataRow dr in dttable.Rows)
{
if (irow == iRowIdx)
{
dr["ColumnNames"] = this.cmbField.Text;
dr["FieldName"] = this.cmbField.SelectedValue;
}
irow++;
}
}
CheckAlias(iRowIdx, this.cmbField.Text, dgvFilter);
checkcellvalue(this.cmbField.Text, iRowIdx);
CheckSorting();
if (bGroupBySelected == true)
{
this.dgvFilter.Rows[iRowIdx].Cells["GroupBy"].Value = "Group By";
}
this.dgvFilter.DataSource = dttable;
dsFilter.AcceptChanges();
this.cmbField.Visible = false;
}
// checkcellvalue(this.cmbField.Text, iRowIdx);
//MessageBox.Show(arr_Filter[0]);
CheckoutputEnable();
}
I have this code in SelectedIndexChanged
try
{
DataTable dt1 = new DataTable();
DataRowView oDataRowView = cmbField.SelectedItem as DataRowView;
string sValue = string.Empty;
if (oDataRowView != null)
{
sValue = oDataRowView.Row["FieldDescription"] as string;
}
//int count = dttable.Rows.Count - 1;
ComboBox comboBox = (ComboBox)sender;
// Save the selected employee's name, because we will remove
// the employee's name from the list.
string selectedEmployee = (string)sValue;
int count = 0;
int resultIndex = -1;
// Call the FindStringExact method to find the first
// occurrence in the list.
resultIndex = cmbField.FindStringExact(selectedEmployee);
// Remove the name as it is found, and increment the found count.
// Then call the FindStringExact method again, passing in the
// index of the current found item so the search starts there
// instead of at the beginning of the list.
while (resultIndex != -1)
{
cmbField.Items.RemoveAt(resultIndex);
count += 1;
resultIndex = cmbField.FindStringExact(selectedEmployee,
resultIndex);
}
// Update the text in Textbox1.
txtName.Text = txtName.Text + "\r\n" + selectedEmployee + ": "
+ count;
}
//}
catch (Exception ex)
{
}
But it throws an exception, say that "items collection cannot be modified when the datasource property is set." I don't know how to fix this exception error, I think that's my only problem when removing an item on the combobox.
Please do help me on this one. Thanks in advance!
Use a BindingSource for your DataSource and CurrentItemChanged to react of changed items in CBO:
this.source = new BindingSource();
this.source.DataSource = loDs.Tables[0];
this.cmbField.DataSource = this.source;
this.source.CurrentItemChanged += source_CurrentItemChanged;
Example for eventHandler:
private void source_CurrentItemChanged(object sender, EventArgs e)
{
System.Data.DataRowView view = this.source.Current as System.Data.DataRowView;
if (view != null)
{
System.Diagnostics.Debug.WriteLine(view[0].ToString());
}
}
You can remove an item from the source like this:
this.source.RemoveAt(this.source.Find("FieldName", "PATIENTNAME"));
Show Details: A Detailed Data Binding Tutorial
You can't modify the Items collection when it comes from / is bound to a DataSource. Instead you need to modify the DataSource itself.
To delete the SelectedItem from the DataSource you can try this:
DataRowView item = cmbField.SelectedItem as DataRowView;
if (item != null) item.Delete();
I have performed enormous amount of Google search on this topic but couldn't really find the proper answer to this question. The solution might be simple, but I am a beginner to C# ASP.NET.
I have some code that is taking and storing user inputs from a dropdown list and a textbox into its individual List. I am trying to display both lists in a single gridview as individual columns. For an example, when a user selects a product and type in the quantity and hits the add button, it should display the details in a single row of a gridview. Now I have achieved saving the data into a list but cannot get it to display it in a single row.
Here is my code:
List<string> productIdList = new List<string>();
List<string> productTemp = new List<string>();
List<string> quantityList = new List<string>();
List<string> quantityTemp = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
productTemp = (List<string>)ViewState["productId"];
quantityTemp = (List<string>)ViewState["quantity"];
string str1 = Convert.ToString(productTemp);
string str2 = Convert.ToString(quantityTemp);
if (str1 != "")
{
if (productTemp.Count != 0)
{
foreach (string ids in productTemp)
{
productIdList.Add(ids);
}
}
}
if (str2 != "")
{
if (quantityTemp.Count != 0)
{
foreach (string qtys in quantityTemp)
{
quantityList.Add(qtys);
}
}
}
}
}
protected void btnContinue_Click(object sender, EventArgs e)
{
productIdList.Add(ddlProduct.SelectedValue.ToString());
quantityList.Add(txtQuantity.Text);
ViewState["productId"] = productIdList;
ViewState["quantity"] = quantityList;
txtQuantity.Text = "";
ArrayList testList = new ArrayList();
testList.AddRange(productIdList);
testList.AddRange(quantityList);
grdTest.DataSource = testList;
grdTest.DataBind();
grdProduct.DataSource = productIdList;
grdProduct.DataBind();
grdQuantity.DataSource = quantityList;
grdQuantity.DataBind();
}
}
The gridview currently present are for test purpose to check if data persists after every click of button. grdTest is what I am using for trying to display my list as columns.
Final would be something like this:
Name Qty
----- -----
Name1(list1) 5(list2)
Thanks!
You can use Linq to create List of object with Name and Qty from two lists like below
var temp = productIdList.Zip(quantityList, (n, w) => new { Name = n, Qty = w });
grdTest.DataSource = temp.ToList();
grdTest.DataBind();
Gridview you have to show both name and quantity in one row, if you join name and quantity to a one list it will not display as you expected ( all will show in one column)
we can create new class with Name and Qty as properties and create List of items by iterating though productIdList and quantityList.
Read more about Enumerable.Zip