dropdown selected item and repose.redirect - c#

I have two dropdownlist in my project and get the items from sql server. One of them show list of something (And I named it DropdownSoore) and another one show list of members of it (And I named it DropdownAye) that update when select an item from DropdownSoore. then when select an item from DropdownAye go to page of them by forwarding query string. I have no problem to updating DropdownAye but when I select item from it and redirect to page of it, the DropdownAye lose the selected item and show the first item (as default) and index to query string in url.
what should I do?
Excuse me about my grammer, I'm not English...
I set DropdownSoore:
<asp:DropDownList ID="DropDownListSoore" runat="server" class="nav-link btn btn-outline-secondary dropdown-toggle" aria-haspopup="true" aria-expanded="true" AutoPostBack="True"></asp:DropDownList>
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
string IdSoore = Convert.ToString(dt.Rows[i]["IdSoore"]);
string NameSoore = Convert.ToString(dt.Rows[i]["NameSoore"]);
DropDownListSoore.Items.Add(IdSoore + "." + NameSoore);
}
string forwardedIdSoore = Request.QueryString["IdSoore"];
if (forwardedIdSoore != null)
{
DropDownListSoore.Items.FindByValue(forwardedIdSoore);
}
And then set DropdownAye:
<asp:DropDownList ID="DropDownListAye" runat="server" class="nav-link btn btn-outline-secondary dropdown-toggle" aria-haspopup="true" aria-expanded="true" OnSelectedIndexChanged="DropDownListAye_SelectedIndexChanged" AutoPostBack="True"></asp:DropDownList>
DropDownListAye.Items.Clear();
for (int i = 0; i <= dt1.Rows.Count - 1; i++)
{
DropDownListAye.Items.Add(Convert.ToString(dt1.Rows[i]["NumberAye"]));
}
int iSelectedAye = Convert.ToInt32(DropDownListAye.SelectedIndex) + 1;
string SelectedAye = Convert.ToString(dt1.Rows[iSelectedAye]["IdAye"]);
Session["SSelectedAye"] = SelectedAye;
string forwardedIdAye = Request.QueryString["IdAye"];
if (forwardedIdSoore != null)
{
DropDownListSoore.Items.FindByValue(forwardedIdAye);
}
in page_Load. and dont have problem to update DopdownAye but when I used it to redirect always get IdAye=1 in url and show the first item of DropdownAye ...:
protected void DropDownListAye_SelectedIndexChanged(object sender, EventArgs e)
{
int SelectedAye = Convert.ToInt32(Session["SSelectedAye"]);
int SelectedSoore = Convert.ToInt32(DropDownListSoore.SelectedIndex) + 1;
string forward = "~/contentAye.aspx?IdSoore=" + SelectedSoore + "&IdAye=" + SelectedAye;
Response.Redirect(forward);
}
I try !IsPostBack but dont have utility too.
I do all thing I think and i dont know what shoild i do.

And where are you loading up these infomration?
Remember, page load ALWAYS fires and triggers for each post-back, for each button click, and any OTHER event on the page that calls code behind.
What does the above really mean?
Well, it means that you need to ONLY ONE TIME load up the drop downs, the gridview(s), or whatever else you have.
So, for the last 200+ web pages I have built, I ALWAYS have this code stub in the page load event:
so this markup:
<h3>Select Hotel</h3>
<asp:DropDownList ID="DropDownList1" runat="server"
DataValueField="ID"
DataTextField="HotelName" Width="356px">
</asp:DropDownList>
<br />
<br />
<asp:Button ID="Button1" runat="server"
Text="Show/get/display drop selection" OnClick="Button1_Click"
CssClass="btn" />
<br />
<h3>Selected result</h3>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
and code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// load up data, controls etc.
string strSQL =
"SELECT ID, HotelName FROM tblHotelsA ORDER BY HotelName";
DataTable dt = General.MyRst(strSQL);
DropDownList1.DataSource = dt;
DropDownList1.DataBind();
DropDownList1.Items.Insert(0, new ListItem("Please Select Hotel", ""));
}
}
protected void Button1_Click(object sender, EventArgs e)
{
string sResault =
$#"dropdown list value (pkid) = {DropDownList1.SelectedItem.Value}
<br/>
Dropdown list Text (Hotel) = {DropDownList1.SelectedItem.Text}";
Label1.Text = sResault;
}
and the result:
SUPER important:
If I leave out the !IsPostBack test in page load, then for EVERY button click, the dropdown list re-load code will trigger, and runs BEFORE your button stubb, or post back. As a result, I will see/find/get no valid value from the drop down list, since page load ALWAYS runs before the given code stub, and thus if page load "every time" re-loads the data, then it will blow out the choosen value in the drop down list.
So, loading up of grids, data, dropdowns etc. can ONLY occur one time in page load, since page load ALWAYS runs before each button or event code stub you have behind.
If you thus only load up the controls and dropdowns on the first REAL page load, then the values the user selects in those dropdowns should work, but only will work if you ALWAYS include that all important if (!IsPostBack) code stub in your page load event.
Now, of course in place of that button to loadup + display the dropdown list into that label?
Well, of course that button click may well (like often) jump or navigate to another page. So, in place of that code to fill out the selected value(s) into that lable, we could pass the selected value to the next page. And how to do that? Well, you can use session(), you can use parmaters in the URL, or you can even use a post-back URL, and then the WHOLE previous page becomes available (Page.Previous), which then in theory allows you to grab ANY and ALL values from the previous page.
but, say we choose session() to pass the value, then this:
Session["HotelPK"] = DropDownList1.SelectedItem.Value;
Response.Redirect("GridFun3.aspx");

Related

dealing with GridView and Custom Validation, both client and serverside

I'm not quite sure how to solve this problem.
What I'm trying to do:
Go through a gridview with multiple rows, and force the user to enter in specific values if certain textboxes or drop down lists are left on the default value.
What I tried:
Tried client side requirements, by use of the focusout event in javascript. Focus goes onto these fields depending on the previous selections users make, that part works. My code:
var row = $(this).closest('tr');
var text = $(row).find("input[name*='txtCurriculum']").val('enter lesson/unit name here');
var ddl = $(row).find("select[name*='ddlCurrAdditions']");
$(ddl).focusout(function () {
if (ddl.val == "-select curriculum name-") {
$(ddl).focus();
alert("select a curriculum name before moving on");
}
});
$(text).focusout(function () {
if (text.val == 'enter lesson/unit name here') {
$(text).focus();
alert('enter in a lesson or unit name before moving on');
}
});
It never fired properly. the ddl focusout would fire, but wouldn't stop firing until I exited and went back to the page. the text focusout would never fire.
Tried server side validation, with the custom validation feature.
protected void cv1_ServerValidate(object source, ServerValidateEventArgs args)
{
CustomValidator cv = ((CustomValidator)(source));
GridViewRow gvr;
//if (FormCGrid.Rows)
foreach (GridViewRow row in FormCGrid.Rows)
{
//string ddl = ((DropDownList)row.FindControl("ddlCurrAdditions")).SelectedItem.Text;
string txtC = ((TextBox)row.FindControl("txtCurriculum")).Text;
bool ddl = ((DropDownList)row.FindControl("ddlCurrAdditions")).Visible;
if (txtC == "enter lesson/unit name here")
{
args.IsValid = false;
cv.ErrorMessage = string.Format("Please enter the Additional program name on row {0}", row.RowIndex);
}
else if (ddl == true)
{
cv.ErrorMessage = string.Format("Enter your lesson or unit for the curriculum selected on row {0}", row.RowIndex);
args.IsValid = false;
}
}
}
I tried to loop through the rows of the gridview here, checking the named dropdown for visibility (hidden until another dropdownlist reveals it, dependent on the value chosen there) and the textbox for the default value, yet this did not work either. It never fired at all. Any suggestions welcome.
I am generally ok with most programming/coding issues, but I find that working with the asp.net gridview, all of my techniques get thrown out the window.
Ok, there are two ways to do this, and you can use js quite easy here. However, lets go with a 100% server side code. I think sticking to server side code is easier.
Next up? I actually STONG suggest to use a listview in place of a gridview WHEN you plan to edit data. The reason is simple - the ListView does not require those "irratating" "item template" over and over for each asp.net control you want to drop/have in that grid display. Now to be fair, say 2-3 controls - then grid view is ok, but for more, then I really find that the listview starts to win here big time (no need for the item template).
The "trick" with listview is of course to setup a datasoruce on the web page, let it generate the markup, and then blow out (delete) all templates except for the item template. And then delete the datasourc1 item on the page, and remove the datasource1 setting from the list view.
However, lets go with the grid view - this will thus be some what "more messy"
So, we going to fill out the grid - and say we want a city combo box - MUST be selected. And lets toss in a basic check for say LastName also must be entered.
So, we have a city combo box (database driven). And say lets toss in a drop down for a hotel rating (1-5) - but that's only 5 choices - so we have that dropdown with the list in mark-up. (so two combo examples to show how this works).
So, say we have a grid like this, and we hit save, we get this result:
Now, of course we would fancy up that message box area. And in fact, we could VERY easy drop in jQuery.UI and make that cute div on the right appear in a dialog box (and we can trigger that box + jQuery.UI dialog display even from our server side code behind - but lets try and keep this short - but I would fancy up that error message area).
Ok, first the markup:
Just a simple grid, but "a bit messy" due to those "item Templates - (if you not figured this out, I really dislike those template things!!! - and with listview you don't need them!! - just drop in pure clean asp.net controls for the grid). Anyway:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:TemplateField HeaderText="HotelName" >
<ItemTemplate><asp:TextBox id="HotelName" runat="server" Text='<%# Eval("HotelName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="FirstName" >
<ItemTemplate><asp:TextBox id="FirstName" runat="server" Text='<%# Eval("FirstName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="LastName" >
<ItemTemplate><asp:TextBox id="LastName" runat="server" Text='<%# Eval("LastName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="City">
<ItemTemplate>
<asp:DropDownList ID="cboCity" runat="server" DataTextField="City"
DataValueField = "City" Width="110px">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active">
<ItemTemplate><asp:CheckBox id="Active" runat="server" Checked = '<%# Eval("Active") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Rating">
<ItemTemplate>
<asp:DropDownList ID="cboRating" runat="server" SelectedValue = '<%# Eval("Rating") %>' >
<asp:ListItem Value="1">Poor</asp:ListItem>
<asp:ListItem Value="2">Just Ok</asp:ListItem>
<asp:ListItem Value="3">Ok</asp:ListItem>
<asp:ListItem Value="4">Good</asp:ListItem>
<asp:ListItem Value="5">Excellent</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div id="ErrorDialog" style="display:normal;float:left;padding-left:30px;width:20%" runat="server">
<asp:TextBox ID="txtErrors" runat="server" TextMode="MultiLine" Style="width:100%" Rows="20" ></asp:TextBox>
</div>
<div style="clear:both;padding-top:20px">
<asp:Button ID="cmdSave" runat="server" Text="Save" />
<asp:Button ID="cmdUnDo" runat="server" Text="UnDo" Style="margin-left:20px"/>
</div>
Ok, now on SO? Gee, that is about the total max markup I would post in one shot - beyond above, we approach the "not very nice" post territory.
Ok, so lets look at the code to load up this grid. We have this code:
public class EditHotelsG : System.Web.UI.Page
{
private DataTable rstTable = new DataTable();
private DataTable rstCity = new DataTable();
protected void Page_Load(object sender, System.EventArgs e)
{
if (System.Web.UI.Page.IsPostBack == false)
{
ErrorDialog.Visible = false;
LoadGrid();
ViewState["rstTable"] = rstTable;
ViewState["rstCity"] = rstCity;
}
else
{
rstTable = ViewState["rstTable"];
rstCity = ViewState["rstCity"];
}
}
public void LoadGrid()
{
// load up our drop down list from database (city)
string strSQL;
strSQL = "SELECT City from tblCity Order by City";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
cmdSQL.Connection.Open();
rstCity.Load(cmdSQL.ExecuteReader);
// now load up main grid view
strSQL = "SELECT ID, FirstName, LastName, HotelName, City, Active, Rating from tblHotels ORDER BY HotelName";
cmdSQL.CommandText = strSQL;
rstTable.Load(cmdSQL.ExecuteReader);
GridView1.DataSource = rstTable;
GridView1.DataBind();
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
// set combo box data source
if (e.Row.RowType == DataControlRowType.DataRow)
{
// setup city drop down list
DropDownList cboDrop = e.Row.FindControl("cboCity");
cboDrop.DataSource = rstCity;
cboDrop.DataBind();
cboDrop.Items.Insert(0, new ListItem(string.Empty)); // add blank row
cboDrop.Text = rstTable.Rows(e.Row.RowIndex).Item("City").ToString;
}
}
}
Ok, now that is not all that much code. And a good part was setting up that combo box. Since the cbo box (dropdown list) was database driven, then we have to bind + setup for each row. So, that cost us a good chunk of our coding time.
Note however how we persist the database soruce (table). We do that, since we want to with A LOT LESS code, update the whole database behind in ONE shot. By peristing that table, then we
Transfer data from Grid to table
Save the table to database in one shot
So, this reduces our coding efforts by a truckload.
The code to save our data, thus becomes this gem:
(and note how we ALSO put in our validation code).
protected void cmdSave_Click(object sender, EventArgs e)
{
// pull gride rows back to table.
bool bolDataOk = true;
txtErrors.Text = "";
foreach (GridViewRow rRow in GridView1.Rows)
{
int RecordPtr = rRow.RowIndex;
DataRow OneDataRow;
OneDataRow = rstTable.Rows(RecordPtr);
OneDataRow.Item("HotelName") = rRow.FindControl("HotelName") as TextBox.Text;
OneDataRow.Item("FirstName") = rRow.FindControl("FirstName") as TextBox.Text;
OneDataRow.Item("LastName") = rRow.FindControl("LastName") as TextBox.Text;
OneDataRow.Item("City") = rRow.FindControl("cboCity") as DropDownList.Text;
OneDataRow.Item("Active") = rRow.FindControl("Active") as CheckBox.Checked;
OneDataRow.Item("Rating") = rRow.FindControl("cboRating") as DropDownList.SelectedValue;
// check for missing City, or LastName
if (IsDBNull(OneDataRow("City")) | OneDataRow("City") == "")
{
bolDataOk = false;
if (txtErrors.Text != "")
txtErrors.Text += Constants.vbCrLf;
txtErrors.Text += "Missing City on row = " + (rRow.RowIndex + 1).ToString;
}
if (IsDBNull(OneDataRow("LastName")) | OneDataRow("LastName") == "")
{
bolDataOk = false;
if (txtErrors.Text != "")
txtErrors.Text += Constants.vbCrLf;
txtErrors.Text += "Missing lastName on row = " + (rRow.RowIndex + 1).ToString;
}
}
ErrorDialog.Visible = !(bolDataOk);
// now send table back to database with updates
if (bolDataOk)
{
string strSQL = "SELECT ID, FirstName, LastName, City, HotelName, Active, Rating from tblHotels WHERE ID = 0";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);
daupdate.Update(rstTable);
}
}
}
Now, once again, that above code snip is a wee bit long - and is aobut the max size of a code snip for SO. I would perhaps consider breaking out that above last code into 2 or even 3 routines.
but, all in all, the above shows quite a few tricks, and approaches here.
As noted, I was going to post how you can/could verify using client side code, ,but the OVER ALL idea of saving back the whole grid with one database update? Well, I would use that trick with a listview, gridview, and even if I was doing client side js verification? I will still use the bulk of the above design pattern.
And the un-do button? Well, I never finished that part - but it would just call the same code as the first page load (postback - false, and you would simply re-bind the grid from the database source for the un-do button.

Calling a server side method from a dynamically generated button inside an update panel

Lets preface this with the fact that I am learning ASP.NET C# and this is my first "real" project so there is a good chance I am missing something obvious, I apologize in advance.
I am working on a web page that displays three columns. The first is "Categories", a user should be able to select a category then have a list of items to choose from appear in the second column "Items". When they click an item the third column should show details about said item. For the most part this is a classic Master/Detail scenario except we take it a step further and do Master/Detail/Detail.
To achieve this I am generating dynamic buttons on Page_Load() in the "Categories" column. In addition I have added a debug line when the page loads, this is important later.
protected void Page_Load(object sender, EventArgs e)
{
//DB query to get categories omitted
for (int i = 0; i < categories.Rows.Count; i++)
{
Button btn = new Button();
btn.Click += new System.EventHandler(CategorySelected_Click);
btn.Attributes["runat"] = "server";
btn.ID = "CatSelBtn" + i;
btn.Attributes["data-categoryid"] = qry.GetCategories().Rows[i]["id"].ToString();
//And some other non-relevant attributes
CategoriesPane.Controls.Add(btn);
}
System.Diagnostics.Debug.WriteLine("Page Loaded");
}
As you may have noticed these buttons have a Click event handler that calls the method CategorySelected_Click(). These buttons all generate successfully and clicking on them results in that method being successfully called. This method is set up in a similar fashion, it grabs a list of items then generates buttons for the items, of course this needs to be done asynchronously so it doesn't reset the user's category selection, so this time it is all contained with an update panel.
C#
protected void CategorySelected_Click(object sender, EventArgs e)
{
//DB query to get items omitted
Button btn = (sender as Button);
string categoryid = btn.Attributes["data-categoryid"].ToString();
for (int i = 0; i < items.Rows.Count; i++)
{
if (items.Rows[i]["Category"].ToString() == categoryid)
{
Button ibtn = new Button();
ibtn.Click += new System.EventHandler(this.ItemSelected_Click);
ibtn.Attributes["runat"] = "server";
ibtn.ID = "ItmSelBtn" + i;
ibtn.Attributes["data-itemid"] = qry.GetItems().Rows[i]["id"].ToString();
//And again some none relevant attributes here
ItemsParent.Controls.Add(ibtn);
}
}
ItemsPanel.Update();
}
ASP
<div class="col-md-2 items-pane">
<asp:UpdatePanel ID="ItemsPanel" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
<div id="ItemsParent" runat="server">
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
<div class="col-md-8 view-pane">
<asp:UpdatePanel ID="ItemDetailsPanel" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
<div id="ItemDetailsParent" runat="server">
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
Again this generates a list of buttons for each item matching the correct category. No issue there, but this time I need the clicked button to call the third and final method which will display the details for the item. This is where things stop working. I assumed that because I was able to generate buttons successfully on Page_Load() that it would work the same inside an update panel. Right now the third method just contains a debug line to check if its firing at all.
protected void ItemSelected_Click(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Item has been selected");
ItemDetailsPanel.Update();
}
In my output console in visual studio when I click on an Item Button control it writes Page Loaded indicating a successful postback but I am not seeing Item has been selected indicating that the third method is firing. I also inserted a breakpoint there but it is not being reached.
I initially thought I needed to add an asyncpostback trigger for each button generated to my update panel but that did not seem to resolve that issue, and because I can now see that Page_Load() is getting triggered I am pretty sure that isn't the issue. This leads me to believe that the click event is somehow not being registered. So my question to you is this: How do I make a dynamically generated button inside an update panel call a server side method? Any help is greatly appreciated.
You need to attach the event handlers on every postback.
It works for your categories-buttons, because the attaching is executed on every page load.
Do this for all the other items also, e.g. put in your Page_Load something like this:
foreach (var ctrl in ItemsParent.Controls)
{
Button ibtn = ctrl as Button;
if (ibtn != null)
{
ibtn.Click += new System.EventHandler(this.ItemSelected_Click);
}
}

ASP table row count not getting incremented

I have an ASP table, with a dropdownlist and text box in its 1st row. I have a button on click of which a similar row should be added. I have the following function in its button click event.
public void addRow()
{
int flag = Table1.Rows.Count;
DropDownList ddl = new DropDownList();
ddl.ID = "ddl" + (flag + 1).ToString();
TextBox tBox = new TextBox();
tBox.ID = "txt" + (flag + 1).ToString();
TableCell tCell1 = new TableCell();
TableCell tCell2 = new TableCell();
tCell1.Controls.Add(ddl);
tCell2.Controls.Add(tBox);
TableRow tRow = new TableRow();
tRow.Cells.Add(tCell1);
tRow.Cells.Add(tCell2);
Table1.Rows.Add(tRow);
}
This code works fine when adding 2nd row. When I click the button again, the value of flag which should have the value of number of rows of the table is not getting incremented. So a new row doesn't get created. Can you please tell me why the value of flag doesn't get incremented ? Or is their an easier way to do this ? Direct answer or link would be helpful.
Mark up code for Table:
<asp:Table ID="Table1" runat="server" Width="410px">
<asp:TableRow>
<asp:TableCell>
<asp:DropDownList runat="server" ID="ddl1"></asp:DropDownList>
</asp:TableCell>
<asp:TableCell>
<asp:TextBox runat="server" ID="txt1"></asp:TextBox>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
Warning - Big ugly block of text
I'm going to try and explain why what you're trying to do is not as simple as it sounds (or as simple as I'd like it to be) and hopfully give you an alterantive approach, which while it
may not be straight forward, it should be "better".
It looks a high level overview of what you are trying to do is the following:
Give the user the oppotunity to add one or more records to a collection (database) before finalising the save.
It is possible to do this using postback to generate the additional rows/items beofore clicking the final save button. Hover this may not be the easiest, or best, way to do this.
From a technical viewpoint adding dynamic controls has to be handeld in a very specific manner at a specific point in the ASP.net page lifecylce. Dynamic controls also have to be recreated on every post back, so every time a user clicks the "add" button, you will have to re-reate the rows you already have in addition to the new row. This is why you only get the one row in this example. Thats just the adding of the dynaimc controls. Wait till you get to getting data from your dynamic text boxes and drop downs!
From an end users perspective, this approach is also not ideal as every time the user clicks the "add" button the page cycles through the request/response process, which at the minumun cuases a bit of an ugly flash.
Update
But how? I hear you ask. Well here it is (I've simplified it to one column for this example):
ASPX
<asp:Table ID="Table1" runat="server">
<asp:TableRow>
<asp:TableCell><asp:TextBox ID="txt1" runat="server"> </asp:TextBox></asp:TableCell>
</asp:TableRow>
</asp:Table>
<asp:Button ID="btnAdd" runat="server" Text="Add" onclick="Button1_Click" />
<asp:HiddenField ID="hdnRowCount" runat="server" />
<asp:Button ID="btnSave" runat="server" onclick="btnSave_Click" Text="Save" />
<div>
<asp:Label ID="lblResult" runat="server" Visible="false"></asp:Label>
</div>
C#
private int rowCount = 1;
private bool rowNeeded = false;
protected override void OnPreInit(EventArgs e)
{
//Pre-emptively create additional row on post back.
//We'll remove it if we don't need it later
//Controls Have to be added at pre-init to maintain their view state
//Adding a row in the button click event will result in any data
//entered in that row dissapearing from viewstate on next post back
if (IsPostBack)
{
//Get number of additional rows from hidden field
//We're using a hidden form field and Request.Form
//instead of ViewsState and hdnRowCount.value
//because ViewState has not been loaded at this stage
//of the page life cycle
if (!string.IsNullOrEmpty(Request.Form["hdnRowCount"]))
{
rowCount = int.Parse(Request.Form["hdnRowCount"]);
}
for (int i = 0; i < rowCount; i++)
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
TextBox tb = new TextBox();
// +2 as there are existing controls with "1", eg txt1
tb.ID = string.Format("txt{0}",i+2);
tc.Controls.Add(tb);
tr.Cells.Add(tc);
Table1.Rows.Add(tr);
}
}
base.OnPreInit(e);
}
//Add Row Click
protected void Button1_Click(object sender, EventArgs e)
{
//Hold number of additional rows in hidne field
hdnRowCount.Value = (++rowCount).ToString();
//Let the page know we need to keep the row
rowNeeded = true;
}
//An Exmple of how to get your data out
protected void btnSave_Click(object sender, EventArgs e)
{
string s = "";
//Iterate through the table rows finding the controls
//Using count -1 as we still have the pre-emptive row
for(int i = 0; i < Table1.Rows.Count-1; i++)
{
TextBox tb = (TextBox)Table1.Rows[i].FindControl(string.Format("txt{0}",i+1));
s += "," + tb.Text;
}
lblResult.Text = s;
lblResult.Visible = true;
}
protected override void OnLoadComplete(EventArgs e)
{
//Get rid of pre-emptive row if we don't need it
if (IsPostBack)
{
if (!rowNeeded)
{
Table1.Rows.RemoveAt(Table1.Rows.Count - 1);
}
}
base.OnLoadComplete(e);
}
End Update
So, how would I do it? Client side, is the answer to that question. I would use jQuery to create a clone of the first row. You then would need to adjust the id and name attributes of your form fields before appending your new row to the table. You would also need a hidden form field to keep track of the number of hidden rows. When your user finaly hits the "save" button, on the C# side, get the number of additional rows from you hidden field the go old school and use Request.Form[] to get the value of each of your added fields.
This, in my opionion, will be a smoother experience for the end user.
Another, somewhat hacky option,if you have a defined maximum number of additional rows. For this have the mamimum rows, with form controls in the table. You can then either use visible="false" in the aspx and use post back to change that to visible="true" when the user clicks "add". The other option there is to give the row a CSS class that hides the row and then use javascript/jquery to remove the class to make the row visible.
The issue here is that you are not understanding the ASP.Net Page Lifecycle and more importantly how it interacts with dynamic controls (your added controls.)
Unfortunately, we can not answer this question without understanding whether the values in these "dynamically" created controls are used server-side or client-side.
I can guess that:
1) If they are for client side consumption/usage, you are doing wrong. If you need more info ask another (more specific) question.
2) If they are for server side consumption/usage, you must only allow one new record per postback, and should include a "Save" button that will save the current "new" row and cause a page refresh that the user can add a new entry to.
3) See rule #0 (Every rule has exceptions. {This rule applies in so far that you understand the problem at hand.})
Monk

how change textbox text after clicking on a button inside a gridview

i have one textbox and one button both on a gridview , when user clicks on button i want to get the textbox text and save to database then clear the text! i used code below it works fine and saves to database but cant clear the textbox why ?
protected void sendcm_Click(object sender, EventArgs e)
{
try
{
Button sendcm = (Button)sender;
GridViewRow gvrow = (GridViewRow)sendcm.NamingContainer;
int ActivityTypeID = Convert.ToInt32(activity.DataKeys[gvrow.RowIndex].Values["ActivityTypeID"].ToString());
int SourceID = Convert.ToInt32(activity.DataKeys[gvrow.RowIndex].Values["SourceID"].ToString());
TextBox tt = (TextBox)activity.Rows[gvrow.RowIndex].FindControl("cmtextbox");
if (tt.Text != "")
{
BusinessLayer.StatusComment_Table ncm = new BusinessLayer.StatusComment_Table();
ncm.Id = Convert.ToInt32(Session["ID"].ToString());
ncm.Statusid = SourceID;
ncm.Statuscommentdate = System.DateTime.Now;
ncm.Statuscommenttext = tt.Text;
ncm.Save();
tt.Text = ""; // its not working !!!!
}
}
protected void Page_Load(object sender, EventArgs e)
{
SessionLable.Text = Session["ID"].ToString();
if (!IsPostBack)
{
getData();
}
}
public void getData()
{
activity.DataSource = BusinessLayer.Activity_Table.GetByProfileData(ID, -1, activity.PageSize);
activity.DataBind();
}
You need to do this at the UI level.
Use jquery.post to call the method that saves the data.
return something back to the $.post callback to tell jquery that the post s complete,
then do something like $('#mytextfield').val('')
assuming that the text box has an ID. I am assuming this is HTML?
you might need to rebind your grid because from the code that you posted it's not clear that where are you re binding your grid.
You need to enable AjaxPostback in your page. After that, in your Page_Load logic, include the code
if(IsPostBack){...}else{...}
So you can handle the construction of UI elements depending on whether this is a fresh new view of the page or a postback (page refreshed due to user clicking the button). UI elements are sent to the browser, after that, there is no way for the server to change it except to refresh the page itself.
The manual (and the one I recommend) way is to do this via jQuery postback. As pointed out in the other answer, you'll need to setup an endpoint for the client browser to connect. After the server has done its job, return the result to the client. Then use jQuery to update the textbox.
i did this to solve my problem !
<asp:TextBox ID="cmtextbox" type="text" clientid="cmtextbox" TextMode="MultiLine" placeholder="نظر دهید..." Rows="1" style="resize:none" class="form-control" runat="server"></asp:TextBox>
<asp:Button ID="sendcm" style="margin-top:2px;" OnClick="sendcm_Click" class="btn btn-success btn-sm pull-left " OnClientClick="ClearTextbox(this)" runat="server" Text="ارسال" />
</script>
<script type="text/javascript">
ClearTextbox = function (that) {
$(that).prevUntil('div.stop', '[ClientID="cmtextbox"]').val('');
}
</script>

Session in not passed between pages c#

I'm working with VS 2013 and Mysql, in one of my pages I put select query in a gridview in this view and I have a button for each row so that if I press a row button I have a new window opening that has the colum Id (which is the first colum ) from the gridview.
the grid view button code:
<Columns>
<asp:TemplateField ><ItemTemplate><asp:Button ID="gridbutton" runat="server" Text="Plus de détails" OnClientClick="basicPopup();return false;" RowIndex='<%# Container.DisplayIndex %>' OnClick="button_click" /></ItemTemplate></asp:TemplateField>
</Columns>
the code of the button_click method:
protected void button_click(object sender, EventArgs e)
{
Button gridbutton = sender as Button;
int rowIndex = Convert.ToInt32(gridbutton.Attributes["RowIndex"]);
string n = "l'index" + rowIndex + "";
Session["idProjet"] = GridView1.Rows[rowIndex].Cells[2].Text;
//string idProjet = Convert.ToString(Session["idProjet"]);
// Alert.Show(idProjet);
}
I just used the two last lines to make sure that I'm getting the value, and I'm getting the right value.
And this is the code from the second page where I want to get the session value:
protected void Page_Load(object sender, EventArgs e)
{
string idProjet = Convert.ToString(Session["idProjet"]);
Alert.Show(idProjet);
}
But all I'm getting is an empty result.
In you button code you have both onclientclick and click event.
In you clickclick event I guest you are opening the different page. Note that client click executes first. So the new page already gets opened. Your server side event executes later. That is why the session is not available in the new form.
<asp:Button ID="gridbutton" runat="server" Text="Plus de détails" OnClientClick="basicPopup();return false;" RowIndex='<%# Container.DisplayIndex %>' OnClick="button_click" />
In this case you have to pass the idProject as query string to the new page.

Categories

Resources