Exception while using nested repeaters - c#

I have a datatable containing all my data called dtData. That datatable contains task descriptions with a task due date for every task description.
Here is what I want to do:
The user selects the month and year from a dropdown and clicks on a button.
Depending upon the number of days in the selected month, a number of panels are generated. (If there are 30 days, 30 panels are generated).
Each panel would correspond to a day in the month and would display the date accordingly.
If the date displayed on the panel matches the task due date for my data, then the corresponding task description is to be displayed in the panel.
I have been able to render the calendar view as I want it but for some reason, while trying the following code to display the necessary task descriptions, a NullReferenceException is thrown.
I debugged the code and the exception is thrown on the following line for the second time the loop which contains it is run (It runs perfectly fine the for the first time):
DateTime p_time = Convert.ToDateTime(((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[1]);
Here is my complete code:
My aspx:
<asp:Repeater ID="rptr_timeline" runat="server" OnItemDataBound="GetChildData">
<ItemTemplate>
<asp:Panel ID="pnl_timeline" runat="server" BackColor="LightGray" BorderColor="Black" BorderStyle="Solid" BorderWidth="1px">
<span id="span_day">Day</span> <asp:Label ID="lbl_day_number" runat="server" Text='<%# Eval("Day_Number").ToString() %>'></asp:Label>
<span id="span_date">Date:</span> <asp:Label ID="lbl_day_date" runat="server" Text='<%# Eval("Day_Date").ToString() %>'></asp:Label>
<asp:Label ID="lbl_day_name" runat="server" Text='<%# Eval("Day_Name").ToString() %>'></asp:Label><br />
<asp:Repeater ID="rptr_tasks" runat="server">
<ItemTemplate>
<asp:Label ID="lbl_task_name" runat="server" Text='<%# Eval("taskdescription_responsible").ToString() %>'></asp:Label>
</ItemTemplate>
<SeparatorTemplate>
<br /><br />
</SeparatorTemplate>
</asp:Repeater>
</asp:Panel>
</ItemTemplate>
<SeparatorTemplate>
<br />
</SeparatorTemplate>
</asp:Repeater>
And here is my code behind:
protected void Load_Dateline(object sender, EventArgs e)
{
try
{
int counter = 0;
int months_days_number = 0;
int month_selected = 0;
int year_selected = 0;
month_selected = Convert.ToInt32(drpdwn_month.SelectedItem.Value);
year_selected = Convert.ToInt32(drpdwn_year.SelectedItem.Value);
months_days_number = DateTime.DaysInMonth(year_selected, month_selected);
DataTable dtMonthdays = new DataTable();
dtMonthdays.Columns.Add("Day_Number");
dtMonthdays.Columns.Add("Day_Date");
dtMonthdays.Columns.Add("Day_Name");
dtMonthdays.Columns.Add("ProperDate");
for (counter = 1; counter <= months_days_number; counter++)
{
DataRow new_row = dtMonthdays.NewRow();
if (counter < 10)
{
new_row["Day_Number"] = "0" + counter.ToString();
}
else
{
new_row["Day_Number"] = counter.ToString();
}
new_row["Day_Date"] = counter.ToString() + "/" + drpdwn_month.SelectedItem.Value.ToString() + "/" + year_selected.ToString();
DateTime temp_date = new DateTime(year_selected, month_selected, counter);
new_row["Day_Name"] = temp_date.ToString("dddd");
dtMonthdays.Rows.Add(new_row);
}
rptr_timeline.DataSource = dtMonthdays;
rptr_timeline.DataBind();
}
catch (Exception ex)
{
lbl_error.Text = "Something went wrong!<br /><br />" + ex.ToString();
}
}
And the following is called on OnItemDataBound of parent repeater:
protected void GetChildData(Object sender, RepeaterItemEventArgs e)
{
Repeater nestedRepeater = e.Item.FindControl("rptr_tasks") as Repeater;
DataTable dt_new = dtData.Clone();
DateTime p_time = Convert.ToDateTime(((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[1]);
foreach (DataRow dr in dtData.Rows)
{
if (DateTime.Parse(dr["taskduedate_responsible"].ToString()).Equals(p_time.ToString()))
{
dt_new.ImportRow(dr);
}
}
if (dt_new != null && dt_new.Rows.Count != 0)
{
nestedRepeater.DataSource = dt_new;
nestedRepeater.DataBind();
}
}

add check whether currently binding item is an Item. or AlternateItem in your GetChildData method
protected void GetChildData(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//Do binding
}
}

Related

ASP.net prevent gridview row click in edit mode

I have some issue with ASP.net Gridview that I hope people here can help me.
Requirements
Gridview whole row to be clickable to open another page
In editing mode, can change table values through edititemtemplate textbox
Problem
Textbox selection causes the entire row click event to fire and prevents user from changing the textbox text. User can edit table value without opening different page.
ASP Page
<asp:GridView ID="remarksGV1" runat="server" AllowPaging="true" DataKeyNames="REM_ID"
OnRowDataBound="remarksGV1_RowDataBound" OnSelectedIndexChanged="remarksGV1_SelectedIndexChanged"
OnRowEditing="remarksGV1_RowEditing"
OnRowCancelingEdit="remarksGV1_RowCancelingEdit"
OnRowUpdating="remarksGV1_RowUpdating"
AutoPostBack="false"
HeaderStyle-CssClass="thead-dark"
CssClass="table table-striped thead-dark table-borderless table-hover border-0 hand"
AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="No.">
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Title">
<ItemTemplate>
<asp:Label ID="titleLbl" runat="server" Text='<%# Bind("REM_TITLE") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="titleTB" runat="server" />
</EditItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="REM_DESC" HeaderText="Remarks Description" ReadOnly="true" />
<asp:BoundField DataField="CREATE_DATE" DataFormatString="{0:d}" HeaderText="Date Created" ReadOnly="true" />
<asp:BoundField DataField="UPD_DATE" DataFormatString="{0:d}" HeaderText="Last Updated" ReadOnly="true" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button Text="Edit" ID="EditBtn" CssClass="btn-action" runat="server" CommandName="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:Button Text="Update" ID="UpdateBtn" CssClass="btn-action" runat="server" CommandName="Update" />
<asp:Button Text="Cancel" ID="CancelBtn" CssClass="btn-action" runat="server" CommandName="Cancel" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind
private void BindGrid()
{
Debug.WriteLine("BindGrid called");
int proj_code = Int32.Parse(ViewState["proj_cd"].ToString());
ProjectRepository remarksRepository = new ProjectRepository();
var remarks = remarksRepository.GetRemarks(proj_code, proj_task_code, proj_stask1_cd, proj_stask2_cd);
remarksGV1.DataSource = remarks;
remarksGV1.DataBind();
}
protected void Unnamed_Click(object sender, EventArgs e)
{
Launch.PageEvent(this, (LinkButton)sender, ViewState["proj_cd"].ToString());
}
protected void remarksGV1_RowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
switch (e.Row.RowType)
{
case DataControlRowType.Header:
//...
break;
case DataControlRowType.DataRow:
e.Row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(remarksGV1, "Select$" + e.Row.RowIndex.ToString()));
break;
}
}
catch
{
//...throw
}
if (e.Row.RowType == DataControlRowType.DataRow)
{
TextBox titleTB = (e.Row.FindControl("titleTB") as TextBox);
int prj_cd = Int32.Parse(ViewState["proj_cd"].ToString());
ProjectRepository repository = new ProjectRepository();
var remarks = repository.GetRemarks(prj_cd, proj_task_code, proj_stask1_cd, proj_stask2_cd);
Debug.WriteLine("Remarks Count: " + remarks.Count);
TMS_PROJ_REMARK remark = remarks.First(x => x.REM_ID == Convert.ToInt64(DataBinder.Eval(e.Row.DataItem, "REM_ID")));
if (titleTB != null)
{
titleTB.Text = remark.REM_TITLE;
}
}
}
protected void remarksGV1_SelectedIndexChanged(object sender, EventArgs e)
{
int row = remarksGV1.SelectedIndex;
long rem_id = (long)remarksGV1.DataKeys[row]["REM_ID"];
Debug.WriteLine("REM ID: " + rem_id);
Session["edit_remarks"] = true;
Dictionary<string, string> pairs = new Dictionary<string, string>();
pairs["rem_id"] = rem_id.ToString();
pairs["proj_cd"] = ViewState["proj_cd"].ToString();
Launch.ToPage(this, "Project_Remarks_In_2.aspx", pairs);
}
protected void btnAddRemarks_Click(object sender, EventArgs e)
{
Session["new_remarks"] = true;
Dictionary<string, string> pairs = new Dictionary<string, string>();
pairs["proj_cd"] = ViewState["proj_cd"].ToString();
string url = "Project_Remarks_In_1.aspx";
Launch.ToPage(this, url, pairs);
}
private void SetTitle()
{
ProjectRepository repository = new ProjectRepository();
TMS_PROJ_MASTER project = repository.GetProject(Convert.ToInt32(ViewState["proj_cd"]));
this.Title = "Remarks - " + project.PROJ_TITLE;
}
protected void remarksGV1_RowEditing(object sender, GridViewEditEventArgs e)
{
remarksGV1.EditIndex = e.NewEditIndex;
BindGrid();
}
protected void remarksGV1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
// Do stuff
ProjectRepository repository = new ProjectRepository();
GridViewRow row = remarksGV1.Rows[e.RowIndex];
TextBox titleTB = (row.FindControl("titleTB") as TextBox);
long rem_id = Convert.ToInt64(remarksGV1.DataKeys[e.RowIndex].Value);
var db = new THPEntities();
TMS_PROJ_REMARK remark = db.TMS_PROJ_REMARK
.First(x => x.REM_ID == rem_id);
remark.REM_TITLE = titleTB.Text;
remark.UPD_DATE = DateTime.Now;
db.SaveChanges();
// Bind Grid
remarksGV1.EditIndex = -1;
BindGrid();
}
protected void remarksGV1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
remarksGV1.EditIndex = -1;
BindGrid();
}
I suggest in this part of your code, do not add the full line click when you edit the line (I have add one -if- to check for the edit).
switch (e.Row.RowType)
{
case DataControlRowType.Header:
//...
break;
case DataControlRowType.DataRow:
if((e.Row.RowState & DataControlRowState.Edit) != DataControlRowState.Edit)
e.Row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(remarksGV1, "Select$" + e.Row.RowIndex.ToString()));
break;
}

ASP.NET Repeater not binding

I have issues.
One of them is this one.
I'm trying to bind a list of Hyperlinks to a repeater and I think my code looks all good, but my repeater is sadly lacking in anything. It's totally blank (Apart from the header, which is not databound).
I can't see where the problem is, so I'm hoping you guys can point it out to me.
Code:
Markup
<asp:Panel ID="pnlNavMenu" class="navigation" runat="server" Visible="true">
<div class="search-textbox"><div>
<asp:ImageButton ID="btnSearch" class="Search-Icon"
BackColor="White" runat="server" OnClick="btnSearch_Click"
ImageUrl="~/images/Mobile/mobile-search-icon.png" />
<asp:TextBox ID="txtSearch" runat="server" CssClass="Search" onblur="if(this.value == '') { this.value='Enter keyword or product code'; isSet=true; }"
onmouseover="if(this.value == 'Enter keyword or product code') { this.value='';isSet = true; }"
onmouseout="if(this.value == '' && !isSet) { this.value='Enter keyword or product code'; isSet=>false; }"
MaxLength="255" Text="Enter keyword or product code" ontextchanged="btnSearch_Click"/>
<asp:ImageButton ID="btnClear" class="Search-Cancel" BackColor="White" runat="server" OnClick="btnClear_Click" ImageUrl="~/images/Mobile/mobile-search-cancel.png" />
</div>
</div>
<asp:Panel ID="pnlComputers" runat="server" CssClass="nav-item" Visible="true">
<asp:Label id="lblComp" Text="Computers" runat="server" cssclass="Menu-Panel-Header"></asp:Label>
<asp:Repeater ID="rptComputers" runat="server">
<ItemTemplate><asp:HyperLink ID="hlCompCategories" runat="server" CssClass="nav-sub-item"><%#Eval("XW_WEBCATNAME") %></asp:HyperLink></ItemTemplate>
</asp:Repeater>
</asp:Panel
<asp:CollapsiblePanelExtender ID="cpe1" runat="Server" TargetControlID="pnlComputers" CollapsedSize="64" ExpandedSize="192" Collapsed="True" ExpandControlID="lblComp" CollapseControlID="lblComp" AutoCollapse="false" AutoExpand="False" ScrollContents="True" ExpandDirection="Vertical" />
</asp:Panel>
C#
protected void Page_Init(object sender, EventArgs e)
{
if (Session["Customer"] is GPCUser)
{
hlLogInOut.Text = "Log Out";
hlLogInOut.NavigateUrl = "log-in.aspx?logout=1";
hlRegDetails.Text = "My Details";
hlRegDetails.NavigateUrl = "/update-details.aspx";
}
else
{
hlLogInOut.Text = "Log in";
hlLogInOut.NavigateUrl = "/log-in.aspx";
hlRegDetails.Text = "Register";
hlRegDetails.NavigateUrl = "/create-account.aspx";
}
BindCategories();
}
private void BindCategories()
{
if (!IsPostBack)
{
try
{
SqlConnection connect = new SqlConnection();
DataTable Data = new DataTable();
connect.ConnectionString = "SERVER = SERVER-SQL01; Trusted_Connection=yes; DATABASE=PCSQL";
connect.Open();
string query = null;
query = "SELECT * from dbo.STOCK_GROUPS WHERE XW_MAINGROUP = '1' ORDER BY XW_WEBCATNAME ASC";
SqlDataAdapter command = new SqlDataAdapter(query, connect);
command.Fill(Data);
connect.Close();
rptComputers.DataSource = Data;
}
catch (SqlException sqlEX)
{
sqlEX.ToString();
}
}
}
protected void rptComputers_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item | e.Item.ItemType == ListItemType.AlternatingItem)
{
HyperLink hlCompCategories = (HyperLink)e.Item.FindControl("hlCompCategories");
DataRowView dr = (DataRowView)e.Item.DataItem;
hlCompCategories.NavigateUrl = Page.ResolveUrl("~/" + "Computers" + "/" + dr["XW_URL"] + "/index.aspx");
if ((!object.ReferenceEquals(dr["xw_webcatname"], System.DBNull.Value)))
{
hlCompCategories.Text = (dr["xw_webcatname"]).ToString();
hlCompCategories.ToolTip = (dr["xw_webcatname"]).ToString();
}
else
{
hlCompCategories.Text = dr["groupname"].ToString();
hlCompCategories.ToolTip = dr["xw_webcatname"].ToString();
}
}
}
I'm pretty sure that the issue is in the ItemDataBound method because the rest of the panel loads fine (search bar and header, etc.) but none of my links are there.
After
rptComputers.DataSource = Data;
add
rptComputers.DataBind();
Otherwise it won't bind.
You might be missing AutoEventWireup=true in Page header in aspx file.
If not than please try to bind the repeater in the Page_Load event instead binding in Page_Init event.

Pass value from a Repeater row to a textbox on button click in asp.net C#

I have the following repeater wrapped in an Update Panel
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="DropDownList1" EventName="SelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<asp:Repeater ID="skillTable" runat="server">
<ItemTemplate>
<table class="table table-hover">
<tr>
<td>
<asp:ImageButton runat="server" AutoPostBack="True" ID="skillButton" OnClick="skillButton_Click" CommandArgument="<%# Eval(DropDownList1.SelectedValue)%>" class="addText btn btn-success" ImageUrl="~/img/addbut.png" /></td>
<td><asp:Label runat="server" id="skillName" Text='<%# DataBinder.Eval(Container.DataItem, DropDownList1.SelectedValue) %>'></asp:Label></td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
It kicks out the information from my database perfectly, and it has a button right before the text in each row.
The problem that i have is that I need each button on each row to, when clicked, add the specific line of code in that row to a textbox.
foreach (RepeaterItem item in skillTable.Items)
{
string skill = item.DataItem.ToString();
string text = skillList.Text;
if (!string.IsNullOrEmpty(text))
{
if (!text.Contains(skill))
{
text += " | " + skill;
skillList.Text = text;
}
}
else
{
text = skill;
skillList.Text = text;
}
}
UpdatePanel2.Update();
I have also tried this way,
protected void skillTable_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
int d = 0;
if(DropDownList1.SelectedValue == "Business and Finance")
{
d = 1;
}
else if(DropDownList1.SelectedValue == "Computers and Technology")
{
d = 2;
}
else if (DropDownList1.SelectedValue == "Education")
{
d = 3;
}
else if (DropDownList1.SelectedValue == "Customer Service")
{
d = 4;
}
DataRowView drv = (DataRowView)e.Item.DataItem;
string skill = drv[d].ToString();
Session["Table"] = skill;
}
protected void skillButton_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
string skill = (string)(Session["Table"]);
string text = skillList.Text;
if (!string.IsNullOrEmpty(text))
{
if (!text.Contains(skill))
{
text += " | " + skill;
skillList.Text = text;
}
}
else
{
text = skill;
skillList.Text = text;
}
UpdatePanel2.Update();
}
but neither one of them seems to work correctly. Any advice? I havent really used repeaters before this, so If there is any other tool that would work better, I'm open for suggestions.
Thanks in advance!
So I figured it out. What I was missing was a way for my site to specifically narrow down what i needed. I added the code blow to my click method and got rid of the ItemDataBound method and it worked like a charm.
Button button = (sender as Button);
string commandArgument = button.CommandArgument;
RepeaterItem item = button.NamingContainer as RepeaterItem;
var workText = (Label)item.FindControl("workName1") as Label;
string work = workText.Text;
string text = workDetails1.Text;
if (text == " ")
text = "";
if (text == "")
{
if (!text.Contains(work))
{
text +="\u2022 " + work;
workDetails1.Text = text;
}
}
else if (!string.IsNullOrEmpty(work))
{
if (!text.Contains(work))
{
text += "\n\u2022 " + work;
workDetails1.Text = text;
}
else
{
workDetails1.Text = text;
}
}
UpdatePanel4.Update();
Hope this helps someone!

Access dynamically created text box in a custom template for an ajax tab

I have a TabContainer in my aspx page as follows
<asp:TabContainer ID="tabcontainer" runat="server" ActiveTabIndex="0">
</asp:TabContainer>
am creating the tabs for the above containter using C# code on Oninit event of the page
protected override void OnInit(EventArgs e)
{
lstCategories = Service.GetCategories();
numberOfCategories = lstCategories.Count;
CreateTabs();
base.OnInit(e);
}
protected void CreateTabs()
{
try
{
for (int i = 0; i < numberOfCategories; i++)
{
TabPanel asptab = new TabPanel();
asptab.ID = lstCategories[i].Id.ToString();
asptab.HeaderText = lstCategories[i].Name;
MyCustomTemplate obj = new MyCustomTemplate(lstCategories[i].Id);
asptab.ContentTemplate = obj;
tabcontainer.Tabs.Add(asptab);
}
}
catch (Exception ex)
{
}
}
public class MyCustomTemplate : ITemplate
{
public Table tbl;
public TextBox tbxQuantity;
public Image img;
public int countOfItemsPerRow = 2;
public MyCustomTemplate(int paramCategoryID)
{
categoryID = paramCategoryID;
}
public void InstantiateIn(Control container)
{
InitialiseTheProperties();
container.Controls.Add(tblHardware);
}
public Table InitialiseTheProperties()
{
//Intialize the Mater Table
tbl = new Table();
//Create Row for the mater Table
TableRow row = new TableRow();
TableCell cell = new TableCell();
img = new Image();
img.ImageUrl = HttpRuntime.AppDomainAppVirtualPath +"/Images/"+"1.jpg";
cell.Controls.Add(img);
tblHardware.Rows.cells.add(cell);
tbxQuantity = new TextBox();
tbxQuantity.ID ="TbxQuantity";
cell.Controls.Add(tbxQuantity);
tblHardware.Rows.cells.add(cell);
tblHardware.Rows.Add(row);
//return tbl;
}
}
}
now am trying to this on a btnclickevent
public void btnSave_Click(object sender, EventArgs e)
{
try
{
Control cntrl = Page.FindControl("TbxQuantity");
}
catch (Exception ex)
{
}
}
it just returns null. Am i doing something wrong? Kindly Help
As i found the answer to the above question posted by myself, I would like to help fellow folks who encounter the same or similar problem.
string strQuantity=((System.Web.UI.WebControls.TextBox)(((AjaxControlToolkit.TabContainer)(BTN.Parent.FindControl("tabcontainer"))).Tabs[0].FindControl("TbxQuantity"))).Text
Thank you "Stackoverflow" for maintaining the site and I also thank the members who help developers like me.
Your issue isn't with the dynamically added controls, but that the FindControl method doesn't propogate and check all the way down the children stack.
I made a quick helper method below that checks the children until it finds the right control. It was a quick build, so it probably can be improved upon, I haven't tried but you could probably extend the control so you don't have to pass in an initial control. I tested it, however for some reason I couldn't get it to work passing in the Page object, I had to pass in the initial panel I used, but it should get the point across.
Control Finder
public static class ControlFinder
{
public static Control Find(Control currentControl, string controlName)
{
if (currentControl.HasControls() == false) { return null; }
else
{
Control ReturnControl = currentControl.FindControl(controlName);
if (ReturnControl != null) { return ReturnControl; }
else
{
foreach (Control ctrl in currentControl.Controls)
{
ReturnControl = Find(ctrl, controlName);
if (ReturnControl != null) { break; }
}
}
return ReturnControl;
}
}
}
HTML Page
<asp:Panel ID="pnl1" runat="server">
<asp:TextBox ID="pnl1_txt1" runat="server" />
<asp:TextBox ID="pnl1_txt2" runat="server" />
<asp:Panel ID="pnl2" runat="server">
<asp:TextBox ID="pnl2_txt1" runat="server" />
<asp:TextBox ID="pnl2_txt2" runat="server" />
<asp:Panel ID="pnl3" runat="server">
<asp:TextBox ID="pnl3_txt1" runat="server" />
<asp:TextBox ID="pnl3_txt2" runat="server" />
</asp:Panel>
</asp:Panel>
</asp:Panel>
<asp:Button ID="btnGo" Text="Go" OnClick="btnGo_Click" runat="server" />
<asp:Panel ID="pnlResults" runat="server">
<div>pnl1_txt1: <asp:Label ID="lblpnl1txt1" runat="server" /></div>
<div>pnl1_txt2: <asp:Label ID="lblpnl1txt2" runat="server" /></div>
<div>pnl2_txt1: <asp:Label ID="lblpnl2txt1" runat="server" /></div>
<div>pnl2_txt2: <asp:Label ID="lblpnl2txt2" runat="server" /></div>
<div>pnl3_txt1: <asp:Label ID="lblpnl3txt1" runat="server" /></div>
<div>pnl3_txt2: <asp:Label ID="lblpnl3txt2" runat="server" /></div>
<div>unknown: <asp:Label ID="lblUnknown" runat="server" /></div>
</asp:Panel>
Button Click event
protected void btnGo_Click(object sender, EventArgs e)
{
Control p1t1 = ControlFinder.Find(pnl1, "pnl1_txt1");
Control p1t2 = ControlFinder.Find(pnl1, "pnl1_txt2");
Control p2t1 = ControlFinder.Find(pnl1, "pnl2_txt1");
Control p2t2 = ControlFinder.Find(pnl1, "pnl2_txt2");
Control p3t1 = ControlFinder.Find(pnl1, "pnl3_txt1");
Control p3t2 = ControlFinder.Find(pnl1, "pnl3_txt2");
Control doesntexist = ControlFinder.Find(pnl1, "asdasd");
lblpnl1txt1.Text = p1t1 != null ? "Found: " + p1t1.ID : "Not found";
lblpnl1txt2.Text = p1t2 != null ? "Found: " + p1t2.ID : "Not found";
lblpnl2txt1.Text = p2t1 != null ? "Found: " + p2t1.ID : "Not found";
lblpnl2txt2.Text = p2t2 != null ? "Found: " + p2t2.ID : "Not found";
lblpnl3txt1.Text = p3t1 != null ? "Found: " + p3t1.ID : "Not found";
lblpnl3txt2.Text = p3t2 != null ? "Found: " + p3t2.ID : "Not found";
lblUnknown.Text = doesntexist != null ? "Found: " + doesntexist.ID : "Not found";
}

Write GridView to .csv file c# asp.net

I am working on developing a website where customers order directly from our website. I had code working until a few days ago when I changed how the GridView was edited. I had previously set the GridView to AutoGenerate Columns, and have changed that since I needed more functionality for the edit feature. Here is how I create the table (created when user clicks a button to add a quick detail with the GridView):
public void CreateTable()
{
try
{
DataTable table = new DataTable();
if (Session["table"] != null)
table = (DataTable)Session["table"];
else
{
table.Columns.Add("Part Number", typeof(string));
table.Columns.Add("Quantity", typeof(Int32));
table.Columns.Add("Ship-To", typeof(string));
table.Columns.Add("Requested Date", typeof(string));
table.Columns.Add("Shipping Method", typeof(string));
}
DataRow row = table.NewRow();
row["Part Number"] = part;
row["Quantity"] = qty;
row["Ship-To"] = shipto;
row["Requested Date"] = reqdate;
row["Shipping Method"] = shipmthd;
table.Rows.Add(row);
Session["table"] = table;
griditems.DataSource = table.DefaultView;
griditems.DataBind();
}
catch
{
//error message
}
}
This displays the Gridview and allows users to edit/delete the items as they choose. Then I have another button that is displayed when the GridView is created that actually writes the .csv file to the server (my computer for the moment until deployment). Here is the code for that:
protected void orderbtn_Click(object sender, EventArgs e)
{
try
{
//ordernum++;
//custordernum = ordernum.ToString("0000000");
if (userlbl.Visible == false && userlbl2.Visible == false)
{
GlobalList.OnlineOrderNum.Add(custordernum, ordernum);
FileStream fs = new FileStream(#"C:\Web_Order\Orders.Bin", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, GlobalList.OnlineOrderNum);
fs.Close();
fs.Dispose();
///Write CSV File For Order
StringBuilder strBuilder = new StringBuilder();
TextWriter tw = new StreamWriter(#"C:\Web_Order\Order_W" + custordernum.ToString() + ".csv");
foreach (GridViewRow row in griditems.Rows)
{
foreach (TableCell cell in row.Cells)
{
// get cell's text
string cellText = cell.Text;
// add quotes and comma around value and append
strBuilder.Append("\"" + cellText + "\",");
}
strBuilder.Append("\n");
}
// output CSV result
tw.Write(strBuilder.ToString());
tw.Close();
tw.Dispose();
GlobalList.weborder = "W" + custordernum.ToString();
Response.Redirect("~/OrderSubmitted.aspx");
}
else
{
validatelbl.Text = "CANNOT SUBMIT FORM WITH ERRORS. PLEASE CORRECT YOUR ERRORS BEFORE SUBMITTING.";
validatelbl.Visible = true;
userlbl.Text = "Please correct your table with the correct information before submitting your order";
userlbl.Visible = true;
userlbl2.Text = "Are your Part Numbers correct? Are your Quantities in the correct format?";
userlbl2.Visible = true;
}
}
catch
{
//error message
}
}
Here's my edit/delete code for the GridView:
protected void griditems_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
griditems.PageIndex = e.NewPageIndex;
BindData();
}
protected void griditems_RowEditing(object sender, GridViewEditEventArgs e)
{
//Set the edit index.
griditems.EditIndex = e.NewEditIndex;
//Bind data to the GridView control.
BindData();
}
protected void griditems_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
//Reset the edit index.
griditems.EditIndex = -1;
//Bind data to the GridView control.
BindData();
}
protected void griditems_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string valtext = "An error has occured, please check and make sure your editing is in the correct format and try again.";
orderbtn.Visible = false;
try
{
TextBox editpart = (TextBox)griditems.Rows[e.RowIndex].FindControl("partedit");
TextBox editqty = (TextBox)griditems.Rows[e.RowIndex].FindControl("qtyedit");
TextBox editshipto = (TextBox)griditems.Rows[e.RowIndex].FindControl("shiptoedit");
System.Web.UI.WebControls.Calendar editcal = (System.Web.UI.WebControls.Calendar)griditems.Rows[e.RowIndex].FindControl("reqdatecaledit");
DropDownList editshipmthd = (DropDownList)griditems.Rows[e.RowIndex].FindControl("shipmthdedit");
string newpart = editpart.Text.ToString();
int newqty = Convert.ToInt32(editqty.Text);
string newshipto = editshipto.Text.ToString();
string newreqdate = editcal.SelectedDate.ToShortDateString();
string newshipmthd = editshipmthd.SelectedItem.ToString();
//Reset date if calendar date is not changed so it is not null!
if (newreqdate == "1/1/0001")
newreqdate = reqdate;
DataTable dt = (DataTable)Session["table"];
DataRow dr = dt.Rows[e.RowIndex];
dr["Part Number"] = newpart;
dr["Quantity"] = newqty;
dr["Ship-TO"] = newshipto;
dr["Requested Date"] = newreqdate;
dr["Shipping Method"] = newshipmthd;
dr.AcceptChanges();
Session["table"] = dt;
if (validatelbl.Text == valtext)
validatelbl.Visible = false;
griditems.EditIndex = -1;
BindData();
orderbtn.Visible = true;
}
catch
{
validatelbl.Text = valtext;
validatelbl.Visible = true;
}
}
protected void griditems_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
try
{
//DataTable dt = table;
DataTable dt = (DataTable)Session["table"];
if (dt.Rows.Count > 0)
{
dt.Rows.RemoveAt(e.RowIndex + griditems.PageIndex * 10);
griditems.DataSource = dt;
BindData();
}
}
catch
{
validatelbl.Text = "An error occured while processing your request deleting a record. Please try again.";
validatelbl.Visible = true;
}
}
Here's the aspx code for the gridview:
<asp:GridView ID="griditems" runat="server"
onrowdeleting="griditems_RowDeleting" onrowediting="griditems_RowEditing" onrowupdating="griditems_RowUpdating"
AllowPaging="True"
onpageindexchanging="griditems_PageIndexChanging" Onrowcancelingedit="griditems_RowCancelingEdit"
Caption="Order Details" AutoGenerateDeleteButton="True"
AutoGenerateEditButton="True"
AutoGenerateColumns="False" >
<EditRowStyle BackColor="#FF9900" BorderStyle="Double"/>
<HeaderStyle Font-Bold="True" Font-Italic="False" />
<RowStyle HorizontalAlign="Center"/>
<Columns>
<asp:TemplateField HeaderText="Part Number">
<ItemTemplate>
<asp:Label ID = "partlbl" runat="server" Text='<%#Eval("Part Number") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="partedit" runat="server" Text='<%# Eval("Part Number")%>' ></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:Label ID = "qtylbl" runat="server" Text='<%#Eval("Quantity") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="qtyedit" runat="server" Text='<%# Eval("Quantity")%>' ></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Ship-To">
<ItemTemplate>
<asp:Label ID = "shiptolbl" runat="server" Text='<%#Eval("Ship-To") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="shiptoedit" runat="server" Text='<%# Eval("Ship-To")%>' ></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Requested Date">
<ItemTemplate>
<asp:Label ID = "reqdatelbl" runat="server" Text='<%#Eval("Requested Date") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:Calendar ID="reqdatecaledit" runat="server" BackColor="White" BorderColor="#3366CC" BorderWidth="1px" CellPadding="1"
DayNameFormat="Shortest" Font-Names="Verdana" Font-Size="8pt" ForeColor="#003399" Height="200px" Width="220px"
ondayrender="reqdatecal_DayRender" ShowGridLines="True">
<DayHeaderStyle BackColor="#99CCCC" ForeColor="#336666" Height="1px" />
<DayStyle BackColor="White" />
<NextPrevStyle Font-Size="8pt" ForeColor="#CCCCFF" />
<OtherMonthDayStyle ForeColor="#999999" />
<SelectedDayStyle BackColor="#FF9900" Font-Bold="True" ForeColor="#CCFF99" />
<SelectorStyle BackColor="#99CCCC" ForeColor="#336666" />
<TitleStyle BackColor="#003399" BorderColor="#3366CC" BorderWidth="1px" Font-Bold="True" Font-Size="10pt" ForeColor="#CCCCFF"
Height="25px" />
<TodayDayStyle BackColor="#99CCCC" ForeColor="White" />
<WeekendDayStyle BackColor="#CCCCFF" /></asp:Calendar>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Shipping Method">
<ItemTemplate><asp:Label ID="shipmthdlbl" runat="server" Text='<%#Eval("Shipping Method") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="shipmthdedit" runat="server">
<asp:ListItem>FedEx Ground (1-5 Business Days)</asp:ListItem>
<asp:ListItem>FedEx 3 Business Days</asp:ListItem>
<asp:ListItem>FedEx 2 Business Days</asp:ListItem>
<asp:ListItem>FedEx Overnight</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I don't understand why it was working all this time and now all of the sudden it is not working. It creates the file with the new ordernumber as it should, its just the .csv file is empty (no data at all) Any thoughts?
You can correct your path, and replace TextWriter with StreamWriter
var path = Path.Combine("C:\Web_Order\Order_W",custordernum.ToString(),".csv");
StreamWriter tw = new StreamWriter(#path);
Or use directly var.
var tw = new StreamWriter(#path);
Adjust your code with try catch block in order to treat exception if occurs
try
{
}
catch(Exception ex)
{
Console.Write(ex.Message);
throw ex;
}
Not sure why you're using TextWriter here, and you don't need to redirect. Just write to Response.Write().
protected void btnDownload_Click(object sender, EventArgs e)
{
// No error so write as attachment
Response.ContentType = "text/csv";
Response.AddHeader("content-disposition", "attachment;filename=data.csv");
// Write your output here
Response.Write(...);
Response.End();
}

Categories