I'm working on creating a dynamic list of checklists and came to the below implementation. I have been trying for a week now to get the fnameID text values on the submit button click to send the values into the database. I do not want to use the postback oncheckedchanged.on each check because the checklist is over 1000 rows long and each postback/reload wastes too many resources. I just want to be able to use some method to be able to grab the checked values so I can insert them into the database on the submit button "Click Me!" click.
I googled and found the FindControl method but i still am not able to grab the fnameID values. I either get a undefined or it errors out on me. Any help would be greatly appreciated! Thanks!
aspx:
<div id="aGAccountabilityCheckListBox">
"Panel1" runat="server">
<asp:LinkButton ID="LinkButton1" Width="66px" runat="server" onclick="LinkButton1_Click">
Click Me!
</asp:LinkButton>
code behind:
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 50; i++)
{
CheckBox _checkbox = new CheckBox();
_checkbox.ID = "dynamicCheckListBox" + Convert.ToString(i);
Panel1.Controls.Add(_checkbox);
Panel1.Controls.Add(" <span id='fnameID" + i + "' >test" + i + "</span>");
}
}
protected void LinkButton1_Click(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["cnDatabase"].ToString());
SqlCommand cmd = new SqlCommand("usp_CreateUser", cn);
cmd.CommandType = CommandType.StoredProcedure;
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}
Thanks!
State is restored to controls before the load event runs. If your controls don't already exist by then, they'll lose their state and you won't know they were checked. Create your checkboxes in the Init or PreInit event instead.
move the checkbox creation to the CreateChildControls page method
to retrieve checkbox state in the LinkButton1_Click handler you can use the following code
for (int i = 0; i < 50; i++)
{
string cbxId = string.Format("dynamicCheckListBox{0}", i);
CheckBox _checkbox = Panel1.FindControl(cbxId) as CheckBox;
if (_checkbox == null )
continue;
if ( _checkbox.Checked )
//do something
}
Your fnameID's are spans created as a literal control. There is no post back value you are going to get if you set it up that way. It's just arbitrary html or text from the asp.net perspective.
Why are you not using the Text property for CheckBox?
Related
I have created multiple linkbutton on same cell of gridview row. But it's click event is not firing. On click event, I have to get StudentID defined in RowDataBound of Gridview.
protected void gvStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//loop through the cell.
for (int j = 1; j < e.Row.Cells.Count; j++)
{
string[] arrLinks = null;
if (!string.IsNullOrEmpty(e.Row.Cells[j].Text.ToString()) && e.Row.Cells[j].Text.ToString() != " ")
{
arrLinks = e.Row.Cells[j].Text.Split(',');//Rahul-3495,Meera-2323
}
if (arrLinks != null)
{
for (int i = 0; i < arrLinks.Length; i++)
{
LinkButton btnLink = new LinkButton();
string StudentName= (arrLinks[i].Split('-').First()).ToString();//Rahul
string StudentID = (arrLinks[i].Split('-').Last()).ToString();//3495
btnLink.ID ="btn_" + StudentID;
btnLink.Text = StudentName + "<br>";
// btnLink.Click += new EventHandler(StudentButtonsclick);
btnLink.CommandName = "btnLink";
e.Row.Cells[j].Controls.Add(btnLink);
}
}
}
}
}
protected void gvStudent_RowCommand(sender s, GridViewCommandEventArgs e)
{
if (e.CommandName == "btnLink")
{ }
}
<asp:GridView ID="gvStudent" runat="server" AutoGenerateColumns="true"
CssClass="gridview_alter"
OnRowDataBound="gvStudent_RowDataBound" OnRowCommand="gvStudent_RowCommand">
</asp:GridView>
Ok, the problem is that controls that require events that are created "after" the page has been rendered cannot really be wired up. You would have to move the code to a earlier event. So you are free to add controls, but they will in "most" cases be rendered TOO LATE to have events attached. Thus when you click on the link button, nothing fires.
So there are two solutions I can think of that will work.
First, set the control to have a a post back URL, and include a parameter on that post back.
eg this:
Dim lnkBtn As New LinkButton
lnkBtn.Text = "<br/>L" & I
lnkBtn.ID = "cL" & I
lnkBtn.PostBackUrl = "~/GridTest.aspx?r=" & bv.RowIndex
If you put a PostbackUrl, then when you click on the button, the page will post back. However, the grid row events such as rowindex change, or row click event etc. will NOT fire. So, if you willing to have a parameter passed back to the same page as per above, then you can pass the 1-3 (or 1-N) values you have for each control.
Of course that means you now have a parameter on the web page URL (and users will see this). You of course simply pick up the parameter value on page load with the standard
Request.QueryString["ID"] or whatever.
However, another way - which I think is better is to simple wire up a OnClickClick() event in js, and thus do this:
I = 1 to N
Dim lnkBtn As New LinkButton
lnkBtn.Text = "<br/>L" & I
lnkBtn.ID = "cL" & I
lnkBtn.OnClientClick = "mycellclick(" & I & ");return false;"
Now in above note how I am passing "I" to the js routine. You would pass your 200, 300 or whatever value you want.
then you script will look like this:
<script>
function mycellclick(e) {
__doPostBack("MySelect", e);
}
</script>
So above simply takes the value passed from the cell click (and linkbutn), and then does the postback with a dopostback. I used "MySelect", and you can give that any name you want.
Now, in the on-load event, you can simply go like this:
If Request("__EVENTTARGET") = "MySelect" Then
Dim mypassvalue As String = Request("__EVENTARGUMENT").ToString
Debug.Print("row sel for MySelect = " & mypassvalue)
End If
So, you are 100% correct - clicking on those controls does NOT fire server side event, and they are wired up too late for this to occur. so you can and often do say add some columns or controls to a gridview, but they are created and rendered TOO LATE for the events to be wired up (and thus they don't fire when clicked on).
But, you can add a postback to the lnkbutton, and you can also add a OnClickClick() event (JavaScript function call) and they will both work. I don't like parameters in the URL appearing when you click, so I think the js script call as per above works rather nice.
So while in the comments I noted (and suggested) that you have to set the CommandName="Select". This suggesting still holds true (without CommandName = select, then the rowindex will not fire. You can't use just ANY name - it MUST be select. However this ONLY works if the control is part of the grid and not added on the fly. As noted, it might be possible to move the grid event to "earlier" event (page initialize) but it going to be a challenge and will require you to re-organize the page. The most clean, and one that does not require parameters in the URL is adding that js OnClientClick() event. You can however set the controls postbackurl and along with a parameter in the URL, and that also can work well if you open to URL with parameters (I don't like them).
I would recommend using CommandName and OnRowCommand event for GridView. Here is how you should do it:
protected void gvStudent_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//loop through the cell.
for (int j = 1; j < e.Row.Cells.Count; j++)
{
string[] arrLinks = null;
if (!string.IsNullOrEmpty(e.Row.Cells[j].Text.ToString()) && e.Row.Cells[j].Text.ToString() != " ")
{
arrLinks = e.Row.Cells[j].Text.Split(',');//Rahul-3495,Meera-2323
}
if (arrLinks != null)
{
for (int i = 0; i < arrLinks.Length; i++)
{
LinkButton btnLink = new LinkButton();
string StudentName= (arrLinks[i].Split('-').First()).ToString();//Rahul
string StudentID = (arrLinks[i].Split('-').Last()).ToString();//3495
btnLink.ID = "btn_" + StudentID; // Good to concatenate a string instead just a number in the ID.
btnLink.Text = StudentName + "<br>";
btnLink.CommandName = "btnLink"; // Add a CommandName
e.Row.Cells[j].Controls.Add(btnLink);
}
}
}
}
}
protected void GridView1_RowCommand(sender s, GridViewCommandEventArgs e)
{
if (e.CommandName == "btnLink")
{
// Link Button was clicked.
var linkButton = (LinkButton)sender;
if (linkButton != null)
{
var studentId = linkButton.ID.Replace("btn_", ""); // Remove the concatenated string from the id.
// Do stuff with the student id.
// I would highly not recommend getting the id from a button element, as it could be modified using browser inspect elements. Instead use, GridView DataKeys.
}
}
}
You should add RowCommand event in your GridView as well to get it going. e.g:
<asp:GridView runat="server" ID="GridView1" OnRowCommand="GridView1_RowCommand">
<!-- Rest of the elements -->
</asp:GridView>
I am having trouble attaching a click event onto an image that I have stored within a grid view. Basically it is a delete button that will allow the user to delete a specific row depending on where the button is. I have the code in c# ready for it, however, I cannot seem to attach a click event to it.
This is the markup code of the button
<asp:TemplateField HeaderText="Remove" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="imgbDeleteP" runat="server" BORDER="0" CausesValidation="false" ImageUrl="~/img/Del.png" Height="25px" ImageAlign="Middle"
onClick ="gv_Quals_RowCommand" CommandArgument="<%#Container.DataItemIndex%>" CommandName="Remove" />
</ItemTemplate>
onClick ="gv_Quals_RowCommand"
Here is the code in c# for the click event
protected void gv_Quals_RowCommand(object sender, GridViewCommandEventArgs e)
{
if ((e.CommandName == "Remove"))
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = gv_Quals.Rows[index];
DataTable dtCurrentTable = (DataTable)Session["CurrentTable"];
dtCurrentTable.Rows[index].Delete();
if ((dtCurrentTable.Rows.Count < 0))
{
}
else if ((row.Cells[0].Text != "*New*"))
{
int appId = 5000;
//int appId = 1;
string insProg = ("delete from projectunitassignment where UnitId =" + int.Parse(row.Cells[0].Text));
SqlCommand cmd = new SqlCommand(insProg, conn);
cmd.Connection.Close();
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Connection.Close();
RebindCat(appId);
}
}
}
This is the compilation error that I keep getting
CS0123: No overload for 'gv_Quals_RowCommand' matches delegate 'ImageClickEventHandler'
I cannot set the click event through the properties as it is stored within the grid view so I cannot access it through there. Also the click event does not run as I have tested with debugging
The problem is with GridViewCommandEventArgs should be just EventArgs
public void imgbDeleteP_Click(object sender, EventArgs e)
Edit:
I see that in your code you use the Command Argument, so if you want to use that you should see this post
Basically use onCommand instead of onClick or cast the sender to button to get the command argument, something like:
var argument = ((ImageButton)sender).CommandArgument;
Did you try to associate the click event for that grid during page load ?
I think that is because of GridViewCommandEventArgs which commonly used for RowCommand , change it to EventArgs, so that event should be something like this:
protected void gv_Quals_RowCommand(object sender, EventArgs e)
{
ImageButton btn = (ImageButton)sender;
string cmName= btn.CommandName;
string cmArgument= btn.CommandArgument;
if ((cmName == "Remove"))
{
.....
}
}
or to get row index:
GridViewRow gvRow = (GridViewRow)(sender as Control).Parent.Parent;
int index = gvRow.RowIndex;
The first parent is the GridView Cell and the second parent of the GridView Cell is the GridView Row.
Codes of the button inside modalpopup (
protected void btnYes_Click(object sender, EventArgs e)
{
int index = Convert.ToInt32(gvItemAssignment.SelectedRow.Cells[1].Text);
con.Close();
con.Open();
SqlCommand delete = new SqlCommand("UPDATE tblAssignment SET AssignDeleteStatus = 'Deleted' WHERE AssignID = " + index + "", con);
delete.ExecuteNonQuery();
con.Close();
dgvItemAssignment.DataBind();
btnDelete_ModalPopupExtender.Hide();
}
Modalpopup
<asp:ModalPopupExtender ID="btnDelete_ModalPopupExtender" runat="server"
BackgroundCssClass="modalBackground" CancelControlID="btnNo"
PopupControlID="Panel3" TargetControlID="btnRemove">
</asp:ModalPopupExtender>
btnRemove for calling (no codes inside)
Main problem is the Databind on btnYes is not working. Gridview is outside. ill click remove button then the popup shows. Then click btnYes inside, doing all the codes except databind, then popup hides. Tried doing this.Databind(); and also IsPostback on the PageLoad. Very much appreciated if you could help me with this. Stuck in a while.
I am stuck with a problem which I have reduced to code below . I have two buttons on an aspx page.
Both the buttons have runat="server" property and are inside <form runat="server" > tag
btnGetData
protected void btnGetData_Click(object sender, EventArgs e)
{
headlines = masg.Split('*');
//Response.Write(headlines.Length);
cb = new CheckBox[headlines.Length];
for (int i = 0; i < headlines.Length; i++)
{
cb[i] = new CheckBox();
cb[i].Text = headlines[i];
Literal br = new Literal();
br.Text = "<br/>";
Form.Controls.Add(cb[i]);
Form.Controls.Add(br);
}
}
On clicking Get Data button , multiple checkboxes are generated with associated text .
I click on some of the checkboxes and then click on Show button which IF WORKS CORRECTLY should combine selected checboxes text into single string and display it.
btnShow
protected void btnShow_Click(object sender, EventArgs e)
{
for (int i = 0; i < headlines.Length; i++)
{
if (cb[i].Checked)
newmsg += cb[i].Text + '*';
}
Response.Write("<BR><BR><BR>" + newmsg);
}
But once I click on GetData button , the checkboxes are lost as they don't persist . I read about SESSION variables but can't figure out how to apply them .
I have declared below variables as global so that they can be accessed throughout the page.
CheckBox[] cb;
string[] headlines;
string masg;
Please help with code .Please provide me with inputs in code. I will refine my question if I am not able to make something clear.
You need to recreate dynamically created controls on every postback(in Page_Init or Page_Load) due to the statelessness of HTTP. You need to know what you have to recreate. Therefore you can save the number of already created CheckBoxes in a ViewState variable.
You only need to assign the same IDs as before and add them in Page_Load at the latest. If you know the number of controls to create you can derive the ID from the counter variable by appending it to the control-id.
Recommandable readings:
TRULY Understanding Dynamic Controls
Page-Lifecycle
Or you use one of the builtin Data-Bound Control like Repeater that do this automatically. You only have to set their DataSource and call DataBind().
Here are answers of me on similar questions with implementation details:
C#
VB.NET (+ C#)
The functional requirement is to fetch the list of students (3 coloums) from database (SQL Server) and display it on the web page, along with a blank field in front of each row for entering data. Next, to allow the user to enter marks scored by students in the test and update those in the database.
Now, I know this can be done using gridview by having an Update Button Field as separate coloumn. But in that case there would be an update button in front of each row and user would need to click it for each student (more than 100). This is a tedious task for user.
I want that user enters the marks for all the students and then click only 1 button, which would update all the rows.
On button click event we can use foreach loop for GridViewRows, but please help me with user interface. How to make it possible?? How to use single button click instead of 'n' clicks??
Can it be done using gridview? Or is there something else which can accomplish the task??
Thanks
place a textbox inside template field in fourth column
<asp:TemplateField HeaderText="Marks Scored">
<ItemTemplate>
<asp:TextBox runat="server" ID="txtMarksScored" />
</ItemTemplate>
</asp:TemplateField>
Then inside button click event loop through grid view rows and get the textbox to get the value entered.
protected void Submit_Click(object sender, EventArgs e)
{
foreach (GridViewRow gvr in GridView1.Rows)
{
TextBox txtMarksScored = (TextBox)gvr.FindControl("txtMarksScored");
// Hope you understand what to do next?
// txtMarksScored.Text
}
}
A complete solution for multi line editing can be found at Matt Dotsons Blog. I use it in my own application.
What you need to do at minimum, besides registering the new gridview type and exchanging your existing asp:GridView with the new type, is to tell the GridView the ID of your "SaveButton". This button will then trigger the RowUpdating/Updated events for each row that changed.
Please refer to Dotsons Blog post for details and the downloadable sourcecode.
Although very late, but may be someone my look for it. Since you did not mentioned any condition or example of code, so I assume this, below is the code:
private void UpdateAllRecord()
{
StringBuilder query = new StringBuilder();
for (int i = 0; i < GridViewName.Rows.Count; i++)
{
GridViewRow row = GridViewName.Rows[i];
using (SqlConnection con = new SqlConnection(connStr)) //use your connection string
{
con.Open();
SqlCommand cmd1 = new SqlCommand("update YourTable set ColumnName=#ColumnName where Id= " + row.Cells[0].Controls.OfType<TextBox>().FirstOrDefault().Text + " ", con);
cmd1.Parameters.AddWithValue("#ColumnName", row.Cells[5].Controls.OfType<TextBox>().FirstOrDefault().Text);
cmd1.ExecuteNonQuery();
con.Close();
}
}
}
// Now call the UpdateAllRecord() to your button click event or any other event
protected void upload_Click(object sender, EventArgs e)
{
UpdateAllRecord()
}