Repeater control to aggregate data? - c#

I have a table with doctor offices and doctors in those offices that I'm populating to a repeater control. The data coming back is not aggregated. So, if there are 2 doctors in 1 office, there are 2 rows, same office, different doctor.
Is there a way to aggregate the data so the repeater shows 1 office with all of the doctors from that office so I can avoid the duplication?

In your aspx markup:
<table><tr><th>Office</th><th>Doctors</th></tr>
<asp:repeater id="Repeater" runat="server" OnItemDataBound="NextItem" ... >
<ItemTemplate><asp:Literal id="RepeaterRow" runat="server" />
</ItemTemplate>
</asp:repeater>
<asp:Literal id="LastRow" runat="server" />
</table>
In your code behind:
public class Office
{
public string OfficeName {get;set;};
List<string> _doctors = new List<string>();
public List<string> Doctors {get{ return _doctors; } };
void Clear()
{
OfficeName = "";
_doctors.Clear();
}
public override string ToString()
{
StringBuilder result = new StringBuilder("<tr>");
result.AppendFormat("<td>{0}</td>", OfficeName);
string delimiter = "";
result.Append("<td>");
foreach(string doctor in Doctors)
{
result.Append(doctor).Append(delimiter);
delimiter = "<br/>";
}
result.Append("</td></tr>");
return result.ToString();
}
}
.
private string CurOffice = "";
private Office CurRecord = new Office();
void NextItem(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return;
Literal repeaterRow = e.Item.FindControl("RepeaterRow") as Literal;
if (repeaterRow == null) return;
DataRow row = ((DataRowView)e.Item.DataItem).Row;
if ( CurOffice != (string)row["Office"] )
{
repeaterRow.Text = CurRecord.ToString();
repeaterRow.Visible = true;
CurRecord.Clear();
CurOffice = row["Office"];
CurRecord.Office = CurOffice;
}
else
e.Item.Visible = false;
CurRecord.Doctors.Add((string)row["doctor"]);
}
void Page_PreRender(object sender, EventArgs e)
{
LastRow.Text = CurRecord.ToString();
}

I think you'd be best doing the aggregation in the database.

I was considering that but thought there might be a fancier way to do it.
If aggregating in the db, pass a delimeted column and parse it during databinding?

Use the SQL coalesce function
As from SQLTeam.com:
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
This will create a comma delimeted list of employees. You can do this for doctors too

Related

Passing DropDownList SelectedValue to SQL Query throws Input String was not in a Correct Format

I'm working on an ASP.NET webforms page that queries the database for a list of entries in the Study table. These entries are to be passed into the dropdownlist. When a study is selected from the dropdownlist, the studyID is to be passed to the GetResponses method to retrieve associated data from a stored procedure.
I receive Input String was not in a Correct Format with the following snippets:
private DataTable LoadStudies(int iStudyID )
{
ddlStudies.Items.Clear();
ddlStudies.SelectedValue = "0";
DataTable dt = new DataTable();
using (PROTOTYPING db = new PROTOTYPING(ConfigurationManager.ConnectionStrings["SQL"].ConnectionString))
{
var query = (from d in db.Studies
where d.StudyStatus == 0 //Closed...
orderby d.StudyName
select new
{
d.StudyName,
d.StudyID,
});
if (query.Count() > 0)
{
foreach (var a in query)
{
ddlStudies.Items.Add(new ListItem(a.StudyID.ToString()));
}
}
dt.Dispose();
DataView dv = new DataView(dt);
return dt;
}
}
The error is thrown on the Page_Load which is currently written as follows:
protected void Page_Load(object sender, EventArgs e)
{
int iUserID = 0;
if (Session["UserID"] == null)
{
Response.Redirect("Default.aspx");
}
iUserID = Convert.ToInt32(Session["UserID"]);
int iRole = 0;
iRole = Convert.ToInt32(Session["RoleID"]);
if (!Page.IsPostBack)
{
LoadStudies(Convert.ToInt32(ddlStudies.SelectedValue));
GetResponses(Convert.ToInt32(ddlStudies.SelectedValue));
ddlStudies.DataSource = LoadStudies(Convert.ToInt32(ddlStudies.SelectedValue));
ddlStudies.DataTextField = "StudyName";
ddlStudies.DataValueField = "StudyID";
ddlStudies.DataBind();
}
}
How do I resolve the error, which is thrown when assigning the dropdownlist's DataSource to the LoadStudies method?
ddlStudies.SelectedValue is not a valid integer value 0,1,2 etc.
I would wager a guess it's an empty string. Convert.ToInt32(""), which will throw the exception you are experiencing.
Interestingly Convert.ToInt32(null) will return a zero.
Try
Convert.ToInt32(string.IsNullOrWhiteSpace(ddlStudies.SelectedValue) ? null : ddlStudies.SelectedValue)

Check checkboxlist Items as value in querystring in asp.net

I want to mark checkboxlist item selected if it's value found in QueryString. e.g.
www.abcd.com/pproducts.aspx?price=1001-2000|2001-5000|5001-10000.
In this url I am filtering products with 3 different price range. Now I have checkboxlist which contains this prices like below
1001-2000
2001-5000
5001-10000
above-10000
so now I want to it should get selected 1001-2000, 2001-5000, 5001-10000
From below code I am redirecting page & making url
private void priceRange_SelectedIndexChanged(object sender, EventArgs e)
{
string selectedPriceRange = priceRange.SelectedValue.ToString;
foreach (ListItem chk in priceRange.Items) {
if (selectedPriceRange.Contains(chk.Value)) {
chk.Selected = true;
}
}
Response.Redirect((Request.Url.AbsoluteUri) + "?price=" + selectedPriceRange);
}
string price = Request.QueryString["price"];
string[] priceList = price.Split('|');
foreach (string p in priceList)
{
if (chkList.Items.FindByText(p) != null)
{
chkList.Items.FindByText(p).Selected = true;
}
}
Above code will select each checkbox as per the value passed in query sting.

How to pass multiple variables to a repeater using string lists

I've been looking for a way to use my repeater with multiple variables such as Creation date, file path, and parent folder, I was able to data bind to a string list to be able to populate the file path and I have a method that will put text into the labels but it only repeats the first item in the list for all label fields. Is there a way to pass multiple variables to the repeater for each of these fields?
.aspx
<asp:Repeater id="repLinks" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<tr>
<td>
<asp:HyperLink runat="server" NavigateUrl='<%# Container.DataItem.ToString() %>' Text="<%# Container.DataItem.ToString().Split('\\').Last() %>" />
</td>
<td>
<asp:Label ID="CRD" runat="server" Text="Label"></asp:Label>
</td>
<td>
<asp:Label ID="USR" runat="server" Text="Label"></asp:Label>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
.aspx.cs
public List<string> CD = new List<string>();
public List<string> lLinks = new List<string>();
public List<string> folder = new List<string>();
public string root = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Welcomes User
string Uname = Environment.UserName;
UserName.Font.Size = 17;
UserName.Text = "Welcome: " + Uname;
Get_Vars();
//Define your list contents here
repLinks.DataSource = lLinks;
repLinks.DataBind();
}
}
protected void Get_Vars()
{
//gives path and constructs lists for directory paths and file links
root = "C:\\Users\\James\\Documents\\Visual Studio 2015\\WebSites";
//adds files to list
foreach (var path in Directory.GetDirectories(#root))
{
foreach (var path2 in Directory.GetFiles(path))
{
lLinks.Add(path2);
CD.Add(File.GetCreationTime(path2).ToString());
//CD.Add(File.GetCreationTime(path2).Date.ToString("yyyy-mm-dd"));
string[] temp = Path.GetDirectoryName(path2).Split(new string[] { "\\" }, StringSplitOptions.None);
folder.Add(temp[temp.Length-1]);
}
}
}
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
foreach (RepeaterItem item in repLinks.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
for(int k=0;k<CD.Count;k++) {
var lbl = (Label)item.FindControl("CRD");
//int k = 0;
lbl.Text = CD[k];
}
}
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
var lbl = (Label)item.FindControl("USR");
int k = 0;
lbl.Text = folder[k];
k++;
}
}
}
Remove your ItemDataBound event handler. You don't need that just to bind some text to a label. It's better to do that declaratively.
You should encapsulate the data in a model.
public class CD
{
public string Name {get; set;}
public string Link {get; set;
public string Folder {get; set;}
//additional properties about the CD here
}
Then create a list of these, and bind that to your repeater.
List<CD> cds = new List<CD>();
//populate your list with data. Here's manually populating with one
CD cd = new CD
{
Name = "Dark Side of the Moon",
Link = "http://www.google.com/pinkfloyd",
Folder = "C:\\Users\\etc"
};
cds.Add(cd);
repLinks.DataSource = cds;
repLinks.DataBind();
Lastly, strongly type your repeater and then you can access the properties.
<asp:Repeater id="repLinks" runat="server" ItemType="CD" OnItemDataBound="Repeater1_ItemDataBound">
<!-- omit some stuff -->
<%#: Item.Name %>
Don't store related values in unrelated variables. Create an object which represents any given element in your repeater. Something like this:
public class MyObject
{
public string CD { get; set; }
public string Link { get; set; }
public string Folder { get; set; }
}
Use a list of that object as your data source:
public List<MyObject> MyObjects = new List<MyObject>();
And populate that list with your data:
foreach (var path2 in Directory.GetFiles(path))
{
string[] temp = Path.GetDirectoryName(path2).Split(new string[] { "\\" }, StringSplitOptions.None);
MyObjects.Add(new MyObject {
CD = File.GetCreationTime(path2).ToString(),
Link = path2,
Folder = temp[temp.Length-1]
});
}
Bind to the list:
repLinks.DataSource = MyObjects;
repLinks.DataBind();
And in the repeater you can bind to the object's properties:
<%# ((MyObject)Container.DataItem).CD %>
or
<%# ((MyObject)Container.DataItem).Link %>
etc.
Whenever you have a logical grouping of data elements, group them. It becomes a whole lot easier to maintain than trying to keep a bunch of separate variables synchronized.

How do I retrieve and save the data out of a dynamically created control in a dynamically created RadGrid

Ok here is the scenario. I have created a completely data driven Radgrid with only 2 static buttons on the page, Save and Cancel. The Radgrid is created dynamically, as well as all the data in the grid (from MS SQL). Here is the tricky part, I have a template column that will contain a control. The type of control is determined again by the data in SQL. I.e., data is 6, I need to return a RadTextBox populated with data from SQL, 5 = RadComboBox, also populated... you get the jist. I have a total of 50 records, so I have around 50 controls, all populated with data which can change and be saved. That is the hard part. I have been stuck for 2 days trying to figure out how to get to the RadGrids cell level, find the control, determine what type of control it is, retrieve the lastest data from that control and save it back out to the Database. The code works, I just need help finding the controls and saving the data...
I need to hit the Save button, which in turn gets all the data and saves it to db. I cannot show you all my code because the codebehind is close to 600 lines. but I will demonstrate with one.
I am giving the controls IDs based on a unique value from that row, so ID="c" = x where x is the unique value.
page.aspx
<form id="formUnionActivityProtestor" runat="server">
<asp:HiddenField ID="hiCaseId" runat="server" />
<asp:HiddenField ID="hiCaseSequence" runat="server" />
<telerik:RadScriptManager runat="server" ID="RadScriptManager1" ScriptMode="Release">
</telerik:RadScriptManager>
<div id="headDiv">
<h2>Blah blah blah</h2>
<h3>blah zeyblah</h3>
<telerik:RadButton runat="server" ID="btnSaveUA" CausesValidation="true" OnClick="btnSaveUA_Click"
Text="Save Union Activity" Skin="Web20" Font-Size="12px" Width="145" Font-Bold="true">
</telerik:RadButton>
<telerik:RadButton runat="server" ID="btnCancel" OnClientClicking="ReadOnly"
Text="Cancel Changes" Skin="Web20" Font-Size="12px" Width="145" Font-Bold="true">
</telerik:RadButton>
</div>
<hr />
<div id="gridContainer" runat="server">
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
</div>
</form>
page.aspx.cs
protected void Page_Init(object sender, System.EventArgs e)
{
radgrid = new RadGrid();
radgrid.ID = "radgrid";
radgrid.PreRender += new EventHandler(radUAGrid_PreRender);
PlaceHolder1.Controls.Add(radgrid);
this.radgrid.NeedDataSource += new GridNeedDataSourceEventHandler(this.grid_NeedDataSource);
radgrid.ItemDataBound += new Telerik.Web.UI.GridItemEventHandler(this.radgrid_ItemDataBound);
radgrid.MasterTableView.DataKeyNames = new string[] { "q_SortValue" };
radgrid.MasterTableView.AutoGenerateColumns = false;
radgrid.MasterTableView.ShowHeader = false;
radgrid.BorderColor = System.Drawing.Color.Gray;
GridBoundColumn boundColumn;
boundColumn = new GridBoundColumn();
boundColumn.ItemStyle.Width = 600;
boundColumn.ItemStyle.CssClass = "prompt";
boundColumn.DataField = "q_Prompt";
radgrid.MasterTableView.Columns.Add(boundColumn);
GridTemplateColumn templateColumn = new GridTemplateColumn();
templateColumn.ItemTemplate = new TemplateColumn("q_QuestionnaireTypeID");
//templateColumn.ItemStyle.Width = 0;
templateColumn.DataField = "q_QuestionnaireTypeID";
templateColumn.UniqueName = "q_QuestionnaireTypeID";
radgrid.MasterTableView.Columns.Add(templateColumn);
boundColumn = new GridBoundColumn();
boundColumn.Display = false;
boundColumn.ItemStyle.CssClass = "hidecol";
boundColumn.DataField = "t_QuestionnaireTypeDescription";
radgrid.MasterTableView.Columns.Add(boundColumn);
}
public partial class TemplateColumn : System.Web.UI.Page ,ITemplate //adding template fields
{
string fieldName = "";
int controlTypeID = 0;
DataTable dt;
int counter = 1;
UnionActivity refMgr = new UnionActivity(Global.ICEConnectionString);
public TemplateColumn(string fieldName)
{
this.fieldName = fieldName;
}
public int getQuestionTypeID(int count)
{
int k = (from DataRow dr in dt.Rows.OfType<DataRow>()
where (int)dr["q_SortValue"] == count
select (Int32)dr["q_QuestionnaireTypeID"]).FirstOrDefault();
return k;
}
public void InstantiateIn(Control container)
{
if (counter == 1)
{
dt = UnionActivityDataTable.dt;
}
controlTypeID = getQuestionTypeID(counter);
if (controlTypeID == 5)
{
int QID = (from DataRow dr in dt.Rows.OfType<DataRow>()
where (int)dr["q_SortValue"] == counter
select (int)dr["q_QuestionnaireInstanceID"]).FirstOrDefault();
int QQID = (from DataRow dr in dt.Rows.OfType<DataRow>()
where (int)dr["q_SortValue"] == counter
select (int)dr["q_QuestionnaireInstanceQuestionID"]).FirstOrDefault();
string answer = (from DataRow dr in dt.Rows.OfType<DataRow>()
where (int)dr["q_SortValue"] == counter
select (string)dr["a_Answer"]).FirstOrDefault();
DataTable dt1;
dt1 = getDropDownList(QID, QQID);
RadComboBox cb = new RadComboBox();
foreach (DataRow row in dt1.Rows)
{
RadComboBoxItem item = new RadComboBoxItem();
item.Text = row["DisplayValue"].ToString();
item.Value = row["DDID"].ToString();
if (answer == item.Text)
{
cb.SelectedValue = item.Value;
}
cb.Items.Add(item);
item.DataBind();
}
string x = (from DataRow dr in dt.Rows.OfType<DataRow>()
where (int)dr["q_SortValue"] == counter
select Convert.ToString((int)dr["a_QuestionnaireInstanceQuestionID"])).FirstOrDefault();
cb.ID = "c" + x;
container.Controls.Add(cb);
}
}
DataTable getDropDownList(int QID, int QQID)
{
DataTable dt2 = new DataTable();
try
{
using (refMgr)
{ //retrieving qicr_QuestionnaireInstanceCaseReferenceID
using (DataTable getDropDownData = refMgr.DynamicDropDownData(QID, QQID))
{
if (getDropDownData != null)
{
dt2 = getDropDownData;
}
}
}
}
catch (Exception ex)
{
}
return dt2;
}
}
after page load I look at the source and this is the insert for the combobox...
<td class="rcbInputCell rcbInputCellLeft" style="width:100%;">
<input name="radgrid$ctl00$ctl22$c12" type="text" class="rcbInput radPreventDecorate" id="radgrid_ctl00_ctl22_c12_Input" value="Kiosk" readonly="readonly" />
</td>
I need to attach a method to the save button, but I dont know the first place to start. Telerik is good about getting the page built dynamically, but not saving the data back out. (or even finding the controls...)
I have seen something like this done for survey generation. The only difference is that it wasn't using a Grid. Is there a reason why you need to use a grid rather than just dynamically building the controls on the page?
I can suggest a way so that you can easily obtain the values from dynamic controls.
You can introduce an interface that all your survey controls need to implement.
interface ISurveyControl
{
// expose some common properties
int QuestionID {get; set;}
object Value {get; set;}
// and others as required
}
Then create an extension for every type of control that you need in your survey
public class SurveyTextBox : RadTextBox, ISurveyControl
{
public int QuestionID {get; set;}
public object Value
{
get { return Text; }
set { Text = value.ToString(); }
}
}
public class SurveyComboBox : RadComboBox, ISurveyControl
{
public int QuestionID {get; set;}
public object Value
{
get { return SelectedValue; }
set { SelectedValue = value.ToString(); }
}
}
Make sure you use these extended controls when building the survey and populate the common properties correctly.
Then all you need is a helper function to find all ISurveyControl controls from a container, regardless of whether it's a grid or a page.
List<ISurveyControl > FindSurveyControls(Control container)
{
// you can use linq to find all ISurveyControl within the container
// you may need to make this recursive as well
}
You can then iterate through the controls on save, knowing that they hold enough information such as the QuestionID and so on.

display items inside a session variable inside a repeater?

I am trying to get the items stored in a sessions variable into a repeater for users to see. However, I am not entirely sure how to do it (I'm new to session variables). Basically, when users enter in quantities for items on once page the hit submit, they are taken to an "order summary" page, which will display what they plan to purchase. I have successfully set up a session variable to contain the sku and quantity of each product the user selects, but I do not know how to get the information out.
I've stored the information in the session variable as [sku],[quantity];[sku],[quantity];[sku],[quantity] and so on. I figure I must do a split or something based on the commas and semicolons but I am not sure how to do so with a session variable.
The code for the product listing page that contains the information to be stored in the session variable:
public partial class GojoptproductlistSublayout : System.Web.UI.UserControl
{
private void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
Item CurrentItem = Sitecore.Context.Item;
Item HomeItem = ScHelper.FindAncestor(CurrentItem, "gojoMarket");
if (HomeItem != null)
{
Item ProductGroup = HomeItem.Axes.SelectSingleItem(#"child::*[##templatename='gojoMarketOfficeBuildigProductMap']/*[##templatename='gojoProductList']");
if (ProductGroup != null)
{
Item[] LocationList = ProductGroup.Axes.SelectItems(#"child::*[##templatename='gojoProductLocation' and #Active = '1']");
if (LocationList != null)
{
DataSet ds = new DataSet();
DataTable locations = ds.Tables.Add("locations");
locations.Columns.Add("LocationName", Type.GetType("System.String"));
locations.Columns.Add("LocationID", Type.GetType("System.String"));
foreach (Item LocationItem in LocationList)
{
DataRow dr = locations.NewRow();
dr["LocationName"] = LocationItem.Fields["Header"].Value;
dr["LocationID"] = LocationItem.ID.ToString();
locations.Rows.Add(dr);
}
locationRepeater.DataSource = ds;
locationRepeater.DataMember = "locations";
locationRepeater.DataBind();
}
}
}
}
}
protected void SetInner(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType != ListItemType.Footer) & (e.Item.ItemType != ListItemType.Header))
{
Label refID = (Label)e.Item.FindControl("refID");
Label test = (Label)e.Item.FindControl("test");
Repeater areaRepeater = (Repeater)e.Item.FindControl("areaRepeater");
Database db = Sitecore.Context.Database;
Item LocationAreaItem = db.Items[refID.Text];
if (LocationAreaItem != null)
{
Item[] AreaList = LocationAreaItem.Axes.SelectItems(#"child::*[##templatename='gojoProductLocationArea' and #Active = '1']");
if (AreaList != null)
{
DataSet dset = new DataSet();
DataTable areas = dset.Tables.Add("areas");
areas.Columns.Add("AreaName", Type.GetType("System.String"));
areas.Columns.Add("Sku", Type.GetType("System.String"));
areas.Columns.Add("ProductName", Type.GetType("System.String"));
areas.Columns.Add("masterSku", Type.GetType("System.String"));
areas.Columns.Add("masterName", Type.GetType("System.String"));
areas.Columns.Add("Size", Type.GetType("System.String"));
areas.Columns.Add("SkuID", Type.GetType("System.String"));
areas.Columns.Add("AreaID",Type.GetType("System.String"));
areas.Columns.Add("productID", Type.GetType("System.String"));
foreach (Item AreaItem in AreaList)
{
DataRow drow = areas.NewRow();
drow["AreaName"] = AreaItem.Fields["Header"].Value;
drow["AreaID"] = AreaItem.ID.ToString();
areas.Rows.Add(drow);
Item[] SkuList = AreaItem.Axes.SelectItems(#"child::*[(##templatename='gojoPTRefill' or ##templatename = 'gojoPTAccessories' or ##templatename = 'gojoPTDispenser' or ##templatename = 'gojoPTSelfDispensed') and #Active = '1']");
foreach (Item ChildItem in SkuList)
{
Item MarketProduct = db.Items[ChildItem.Fields["Reference SKU"].Value];
drow["productID"] = ChildItem.ID.ToString();
if (MarketProduct != null)
{
Item MasterProduct = db.Items[MarketProduct.Fields["Master Product"].Value];
if (MasterProduct != null)
{
DataRow newRow = areas.NewRow();
if(MasterProduct.TemplateName == "gojoSKUSelfDispensed" || MasterProduct.TemplateName == "gojoSKURefill")
{
newRow["Size"] = MasterProduct.Fields["Size"].Value;
}
else
{
newRow["Size"] = "-";
}
newRow["Sku"] = MasterProduct.Fields["SKU"].Value;
newRow["productID"] = MasterProduct.ID.ToString();
Item MasterProductName = db.Items[MasterProduct.Fields["Complete Product Name"].Value];
if (MasterProductName != null)
{
newRow["ProductName"] = MasterProductName.Fields["Complete Name"].Value;
}
areas.Rows.Add(newRow);
}
}
}
}
areaRepeater.DataSource = dset;
areaRepeater.DataMember = "areas";
areaRepeater.DataBind();
}
}
}
}
protected bool checkQtys(ref int ItemCnt, ref ArrayList LinesToOrder)
{
Repeater locationRepeater = (Repeater)FindControl("locationRepeater");
bool validQtys = true;
string productID = "";
int qty;
qtyErrorMsg.Text = "";
qtyErrorMsgTop.Text = "";
foreach (RepeaterItem repItem in locationRepeater.Items)
{
if (repItem != null)
{
Repeater areaRepeater = (Repeater)repItem.FindControl("areaRepeater");
if (areaRepeater != null)
{
foreach (RepeaterItem skuItm in areaRepeater.Items)
{
if (skuItm != null)
{
Label SkuID = (Label)skuItm.FindControl("SkuID");
Label qtyID = (Label)skuItm.FindControl("qtyID");
PlaceHolder inner = (PlaceHolder)skuItm.FindControl("ProductTable");
if (inner != null)
{
foreach (Control ct in inner.Controls)
{
if (ct is TextBox)
{
TextBox lineQty = (TextBox)ct;
Label prodID = (Label)inner.FindControl("productID");
if (lineQty.Text != "")
{
try
{
int.Parse(lineQty.Text);
productID = prodID.Text;
qty = int.Parse(lineQty.Text);
if (qty > 0)
{
noItemMsg.Visible = false;
noItemMsgTop.Visible = false;
ItemCnt++; //only count items with valid qty values
LinesToOrder.Add(new LineItem(productID, qty));
}
else
{//Qty is 0 or less error
validQtys = false;
qtyErrorMsg.Text = "Quantity must be a number<br />";
qtyErrorMsgTop.Text = "Quantity must be a number<br />";
}
}
catch
{//NaN - display error msg
validQtys = false;
qtyErrorMsg.Text = "Quantity must be a number<br />";
qtyErrorMsgTop.Text = "Quantity must be a number<br />";
}
}
}
}
}
}
}
}
}
}
return validQtys;
}
class LineItem
{//This class will store the product information
public string SKUID;
public int Qty;
public LineItem(string InSKUID, int InQty)
{
this.SKUID = InSKUID;
this.Qty = InQty;
}
}
protected void orderSubmit(object sender, EventArgs e)
{
int ItemCnt = 0;
bool validQtys = true;
ArrayList LinesToOrder = new ArrayList();
Label lb = FindControl("order") as Label;
if (checkQtys(ref ItemCnt,ref LinesToOrder))
{
if (ItemCnt == 0)
{//make sure at least one item with proper qty amount is entered before submitting the order
validQtys = false;
noItemMsg.Visible = true;
noItemMsg.Text = "You must order at least one item<br />";
noItemMsgTop.Visible = true;
noItemMsgTop.Text = "You must order at least one item<br />";
}
if (validQtys)
{//save the information to a session variable and send users to order review page
try
{
foreach (LineItem WorkLine in LinesToOrder)
{
lb.Text += WorkLine.SKUID + ", " + WorkLine.Qty + ";";
}
Session["orderComplete"] = lb.Text;
}
catch (Exception x)
{
Response.Write(x.Message.ToString());
}
Response.Redirect("/united-states/market/office-buildings/obproductmap/OrderReview");
}
}
}
}
Here is the designer code with the repeater that is meant to hold the order summary:
<asp:Repeater ID="orderRepeater" runat="server" >
<headertemplate>
<tr>
<th>SKU</th>
<th>Quantity</th>
</tr>
</headertemplate>
<itemtemplate>
<tr>
<td><%#Eval("sku") %></td>
<td><%#Eval("qty") %></td>
</tr>
</itemtemplate>
</asp:Repeater>
And here is the code behind:
private void Page_Load(object sender, EventArgs e)
{
Item CurrentItem = Sitecore.Context.Item;
Item HomeItem = ScHelper.FindAncestor(CurrentItem, "gojoMarket");
if (Session["orderComplete"] != "")
{
if (HomeItem != null)
{
Item ProductGroup = HomeItem.Axes.SelectSingleItem(#"child::*[##templatename='gojoMarketOfficeBuildigProductMap']/*[##templatename='gojoOrderReview']");
if (ProductGroup != null)
{
//this is where I am confused on how to proceed
}
}
}
}
Everything is working and I did a Response.Write test on the session variable to make sure it had the correct information and it did.
Thanks in advance!
Before I try to address your question, lets take a look at some basics. A Session can hold an object, not just a string object. I would change:
if (Session["orderComplete"] != "")
to
if (Session["orderComplete"] != null && Session["orderComplete"] != "")
if you don't, and Session["orderComplete"] is null, Session["orderComplete"] != "" will throw an error object not set to an instance of an object
And now to your question. Setting your session variable to [sku],[quantity];[sku],[quantity];[sku],[quantity], is not a good idea. For one, its not object oriented and 2, its not going to bind to any repeater or data source. You should create an object and bind a list of those objects to your control:
pseudo code:
class Program
{
static void Main(string[] args)
{
List<Order> orders = new List<Order>();
orders.Add(new Order { Sku = "ABC", Qty = 10});
}
}
public class Order {
public String Sku { get; set; }
public int Qty { get; set; }
}
Then you can bind orders to your repeater. For example:
if (Session["orderComplete"] != null && Session["orderComplete"] != ""){
List<Order> orders = Session["orderComplete"] as List<Order>;
myRepeater.DataSource = orders;
myRepeater.DataBind();
}

Categories

Resources