I have this problem with being able to access certain elements in
GridView -> TemplateField -> EditItemTemplate.
To be more clear, I have textbox and button
(in GridView -> TemplateField -> EditItemTemplate) and only one of them must be visible depending on operation. If I want to edit, button must be visible and if I want to add new user then textbox must be visible. I have added my aspx code for you to check and also C# code-behind. The method in C# code is the one which gets called immidiately when I press "Edit" button which lets to edit account details and permissions for one user. And I want that this method would decide whenever to show textbox or button (I have IsUserInsertMode property for that.)
I would be really grateful for someone who would help me out with this.
<asp:GridView CssClass="grid" ID="gridUsers" runat="server"
AutoGenerateColumns="False" DataKeyNames="id"
DataSourceID="dsrcUserList" GridLines="None"
OnRowCommand="gridUsers_RowCommand" OnDataBound="gridUsers_DataBound"
OnRowUpdating="gridUsers_Updating" OnRowUpdated="gridUsers_Updated" EnableModelValidation="True">
<Columns>
<asp:TemplateField HeaderText="Password" ItemStyle-HorizontalAlign="center" ItemStyle-Width="80px">
<ItemTemplate>
*******
</ItemTemplate>
<EditItemTemplate>
**NEED REFERENCES TO THESE TWO ITEMS IN ORDER TO SET THEIR VISIBILITY**
<asp:Button ID="btnEditPassword" Text="Change" runat="server" CausesValidation="false" OnClick="btnEditPassword_Click" Visible="false"/>
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Text='<%# Bind("Password") %>' Width="74px" MaxLength="50" Visible="true" />
</EditItemTemplate>
</asp:TemplateField>
**LOTS OF CHECKBOXES LIKE THOSE**
<asp:CheckBoxField DataField="AccessTowsRelease" HeaderText="TowsRelease" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessTowsView" HeaderText="TowsView" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessSMS" HeaderText="SMS"
ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
**MY EDIT BUTTON**
<asp:CommandField ButtonType="Link"
ShowEditButton="true" EditText="Edit"
CancelText="Cancel" UpdateText="Save" />
</Columns>
</asp:GridView>
C# code-behind (I have added some of the stuff that I have tried)
// this is called when I press some button which lets me to edit one user data including password
// but when I want to change password, there should be button which would redirect to different
// window to do the password change procedure.
// And when I want to add new user there should be textbox for password, not the button.
protected void gridUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
//Found the way to get the index of current row (represents one row of information which is visible for the client in browser)
int rowIndex = Convert.ToInt32(e.CommandArgument);
//if those would be working I wouldn't be here asking for help
btnEditPassword.Visible = true;
txtPassword.Visible = false;
//Can't cast 'System.Web.UI.WebControls.GridView' to type 'System.Web.UI.WebControls.GridViewRow'
Button btnEditPassword = (Button)((GridViewRow)sender).FindControl("btnEditPassword");
//every attempt to use FindControl gets me null
Button btnEditPassword = (Button)this.gridUsers.Rows[rowIndex].FindControl("btnEditPassword");
// my way to check if it works - if its null then I do can't anything (prints to browser console).
if (btnEditPassword != null) Response.Write("<script>console.log('not null')</script>");
else Response.Write("<script>console.log('null')</script>");
}
The RowCommand-event is raised too early for your case. It's raised before the row is going into edit mode, that's why you don't find the controls of your edit-item-template.
First change your markup to handle the RowDataBound-event:
<asp:GridView ... OnRowDataBound="gridUsers_OnRowDataBound" ...>
Then handle this in the OnRowDataBound-event like this:
protected void gridUsers_OnRowDataBound(object sender, GridViewRowEventArgs e) {
// check if row is in edit state
if ((e.Row.RowState == DataControlRowState.Edit) || (e.Row.RowState == (DataControlRowState.Alternate | DataControlRowState.Edit))) {
// look for the control in the row
Button btnEditPassword = (Button)e.Row.FindControl("btnEditPassword");
}
}
Related
I am trying to incorporate an edit button in a grid view.
However the on row command does not seem to be firing.
I put a break point on the onrowcommand method i have implemented in the code behind.
Here is the View (i substituted the imageurl with xxx's as privacy concern on here):
<asp:GridView ID="GridViewContacts1" runat="server" CssClass="data_table" AutoGenerateColumns="false" OnRowCommand="GridViewContacts1_OnRowCommand" EmptyDataText="There are no contacts for this prospect." >
<AlternatingRowStyle CssClass="alternating_row" />
<Columns>
<asp:BoundField DataField="ContactName" HeaderText="Name" />
<asp:BoundField DataField="ContactTitle" HeaderText="Title" />
<asp:TemplateField HeaderText="Phone" SortExpression="PhoneNumber">
<ItemTemplate>
<%# FormatPhone(Eval("PhoneNumber").ToString()) %>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email"></asp:BoundField>
<asp:TemplateField HeaderText="Edit" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="icmdEditContact" Runat="server" ImageUrl="xxxxx" BorderStyle="None" CommandName="EditContact" CommandArgument='<%# Eval("ContactId") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton CommandArgument='<%# Eval("ContactId") %>' CausesValidation="false" CommandName="DeleteItem" OnClientClick="javascript:return confirm('Are you sure you want to delete this record?')" Runat="server" ID="Linkbutton1"><img src="xxxxx" border="0"/></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
As you will see the OnRowCommand Property of the grid view is : GridViewContacts1_OnRowCommand
Here is the code behind
The problem i'm having is this isn't getting hit :
Any ideas or suggestions ?
I even tried to incorporate without the rowcommand by just using a normal button and click event and it still wouldn't hit the designated codebehind method for that click event.
Do both buttons not work, or just the delete button?
Make sure viewstate is not turned off for the GV, and "always" give each button a "id" - your delete button is missing one.
On the other hand?
I often, and in fact BEYOND often just dump the built in commands for the GV. You actually don't need them.
For any button, image button etc that you drop into your GV (templated column), then you can just add/use/have a plain jane click event, and then use that.
The "bonus" then is you are free to add new buttons, and you don't have to use nor mumble jumpble all of the commands into that one on-row command routine anyway.
So, do check:
make sure view state of gv not turned off
make sure each button has a "id"
make sure you not re-binding the gv on page load each time
(you look to have the all important !IsPostback (good).
However, as noted, I don't use the row commands anymore.
You can do it this way:
Say this GV.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" width="40%" CssClass="table table-hover" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server"
Checked='<%# Eval("Active") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="View" CssClass="btn"
OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And code to load:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL =
#"SELECT * FROM tblHotelsA ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
And we see/get this:
Button click code - each button is SEPERATED - nice!!
So, this code:
protected void cmdView_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
GridViewRow gRow = (GridViewRow)btn.NamingContainer;
int iPK = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
Debug.Print("Database PK = " + iPK);
Debug.Print("Row index click = " + gRow.RowIndex);
Debug.Print("Hotel Name = " + gRow.Cells[3].Text); // non template values
// get value of check box control on this row
CheckBox chkActive = (CheckBox)gRow.FindControl("chkActive");
Debug.Print("Value of active check box control = " + chkActive.Checked);
// hide gv, show edit area.
// bla bla bal
}
Now clicking on a button, we get this output:
Database PK = 16
Row index click = 0
Hotel Name = Batman's Cave
Value of active check box control = True
So,
Note how we use database "datakeys" option. This is VERY improant for secuirty, since the database row PK is NEVER exposted client side.
However, as above shows:
You can easy get the datakeys (row PK id)
You can easy get the row index
you have full use of the row (namingcontainer)
you can use find control etc.
So, really, I see LITTLE reason to use the built in row index command.
You ARE free to add/use/have/enjoy the command arugument for a button, or image button, or link buttion and I'll often use that to add/supply extra information to pass to the button).
But for the public and history?
Check viewestate, add "id" to those buttons that don't have one.
However, all in all, since you can just use/add/have a button click like any other button you drop into a page, then I just continue to use simple plain jane button clicks, and not bother with the GV event model.
Note that naming container trick used above works for repeaters/listview/datalist etc.
First let me preface this with the fact that I know this question has been asked a slew of times. I've tried implementing everything I've read and have not resolved my issue yet.
I have a shopping cart being displayed in a GridView and I am trying to get the update function to work. After I click edit (on the row in question) and I change the value in the textbox, and then click update, I am always getting an empty string returned.
I've read countless posts about it being a PostBack issue, however I have encapsulated my DataBind method within an if(!Page.IsPostBack){} so I dont believe that is my issue.
These are the relevant methods in my CodeFile:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["thisCart"] == null)
{
Session["thisCart"] = new ShoppingCart();
}
thisCart = (ShoppingCart)Session["thisCart"];
if (!Page.IsPostBack)
{
FillData();
}
}
private void FillData()
{
gvShoppingCart.DataSource = thisCart.Items;
gvShoppingCart.DataBind();
if (thisCart.Items.Count == 0)
{
lblGrandTotal.Visible = false;
}
else
{
lblGrandTotal.Text = string.Format("Grand Total = {0,19:C}", thisCart.GrandTotal);
lblGrandTotal.Visible = true;
}
}
protected void gvShoppingCart_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
TextBox txtQuantity = (TextBox)gvShoppingCart.Rows[e.RowIndex].Cells[3].Controls[0];
int quantity = Int32.Parse(txtQuantity.Text);
thisCart.Update(e.RowIndex, quantity);
gvShoppingCart.EditIndex = -1;
FillData();
}
And this is the aspx file:
<asp:GridView ID="gvShoppingCart" runat="server" AutoGenerateColumns="False" OnRowCancelingEdit="gvShoppingCart_RowCancelingEdit" OnRowDeleting="gvShoppingCart_RowDeleting" OnRowEditing="gvShoppingCart_RowEditing" OnRowUpdating="gvShoppingCart_RowUpdating" ClientIDMode="AutoID">
<Columns>
<asp:BoundField DataField="NAME" HeaderText="Product name" ReadOnly="True" />
<asp:ImageField DataImageUrlField="IMAGE" DataImageUrlFormatString="~\Images\{0}" HeaderText="Image" ReadOnly="True">
</asp:ImageField>
<asp:BoundField DataField="PRICE" HeaderText="Price" ReadOnly="True" />
<asp:BoundField DataField="QUANTITY" HeaderText="Quantity" />
<asp:TemplateField HeaderText="Total">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Double.Parse(Eval("PRICE").ToString()) * Int32.Parse(Eval("QUANTITY").ToString()) %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Update" Text="Update"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowDeleteButton="True" />
</Columns>
</asp:GridView>
I'm usually pretty good at finding answers, but this one has got me stumped.
The site crashes after clicking update because the returned value from int quantity = Int32.Parse(txtQuantity.Text); is "" and obviously you cant parse an int from that.
As for the tag of possible duplicate of "ASP.NET validation error message to change labels text." I was unable to find anything that points me in the direction of an answer.
Call FillData() in Page_PreInit. Otherwise, when the ASP.Net runtime goes to restore ViewState for the grid, including your new Textbox data, there's nowhere to put it yet. Remember that every single server event uses a brand new instance of your page class and must rebuild the entire page from scratch.
This was a royal pain to figure out since I'm just learning ASP.net and C#.
When I was able to make this work on an earlier assignment I wasn't using a Master page, with this project I am. The problem lies in the fact that I am using a <form runat="server"> tag in the Master page. Since you can only have one <form runat="server"> tag per page, my GridView wasn't wrapped in one. Once I removed the Master page and added the <form runat="server"> wrapper around the GridView, everything works as intended.
I have a gridview with 2 templatefields, one is a checkbox and the other is a dropdownlist. I want to be able to have the dropdownlist for that row visible if a user selects the checkbox.
<asp:TemplateField HeaderText="Follow-up Needed" ItemStyle-Width="75px">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:CheckBox ID="CBFollowUp" runat="server" AutoPostBack="true"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Follow-Up Assignment" ItemStyle-Width="100px">
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:DropDownList ID="DropDownListFollowUpUser" runat="server" Visible="false"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
I tried to put the logic in the RowDataBound, but on a postback I lose the checkbox selection, but if I do !isPostBack on my Databind, then It won't fire RowDataBound when a checkbox is selected.
I'm not sure where and what logic I need to make to make this fluid, Do I need to do it in the OnCheckedChanged, or javascript?
Thank you for any feedback.
One option would be to use the OnCheckChanged event like you thought. First add it to your CheckBox.
<asp:CheckBox ID="CBFollowUp" runat="server"
AutoPostBack="true"
OnCheckChanged="CBFollowUp_CheckChanged" />
Then handle it in your codebehind. In here you would find your DropDownList that is within the same row as the CheckBox you just clicked and then hide/show it as necessary.
protected void CBFollowUp_CheckChanged(object sender, EventArgs e)
{
CheckBox CBFollowUp = (CheckBox)sender;
GridViewRow row = (GridViewRow)CBFollowUp.NamingContainer;
DropDownList DropDownListFollowUpUser = (DropDownList)row.FindControl("DropDownListFollowUpUser");
DropDownListFollowUpUser.Visible = CBFollowUp.Checked;
}
I have a ListView nested inside the column of a GridView, which looks something like this:
<asp:panel id="myPanel" Runat="server" EnableViewState="False">
<asp:GridView id="myDescription" AutoGenerateColumns="False" Width="100%" runat="server"
OnRowCommand="my_RowCommand" OnRowDataBound="GetDataForListView" EnableViewState="False">
<Columns>
<asp:BoundField DataField="id" HeaderText="ID">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="data1" HeaderText="Thing 1">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="data2" HeaderText="Thing2">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:BoundField DataField="data3" HeaderText="Thing3">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:BoundField>
<asp:TemplateField SortExpression="id">
<ItemTemplate>
<asp:HyperLink id="hlView" runat="server" NavigateUrl="...">View</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Column to contain my list of things">
<HeaderStyle HorizontalAlign="Center"></HeaderStyle>
<ItemStyle HorizontalAlign="Center"></ItemStyle>
<ItemTemplate>
<% /* This is my list view: */ %>
<asp:ListView ID="myListView" runat="server" OnItemCommand="DoSomething" EnableViewState="False">
<ItemTemplate>
<asp:LinkButton ID="lbAttachment" Runat="Server" Text='<%# Eval("FILE_NAME") %>'
CommandName='<%# Eval("ROW_NUM") %>' CausesValidation="False" >
</asp:LinkButton><br/>
</ItemTemplate>
</asp:ListView>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:panel>
The data is successfully binding, but the OnCommand event is not being fired on clicking the LinkButton (nor is any other event for the LinkButton, such as an OnClick event).
The rendered HTML for the link button shows that on clicking it, the page is performing a postback: javascript:__doPostBack('...','')
This means it is going back into my 'Page_Load' and refreshing the contents of the page - the grid view is binded here.
I can stop it from performing a postback by adding this attribute to the LinkButton:
OnClientClick="return false;"
But this only stops the postback from occurring, the OnCommand event still doesn't fire.
Any ideas?
The event signature in the code-behind is:
protected void DoSomething(object sender, CommandEventArgs e) { ... }
I have also tried using an OnItemCommand event on the ListView control with this event signature, but similarly the event is not invoked:
protected void DoSomething(object sender, ListViewCommandEventArgs e)
The OnRowdataBound event on the parent GridView is successfully invoked, it's only the nested ListView that fails to invoke its event.
The code I have shown is for the 2nd GridView on the page, there is another one too, and it is this one which gets binded on the Page_Load event. The Page Load event has a sequence of events as follows, where the 1st GridView (which we'll call GridView1) is bound:
Page_Load
Data for GridView is retrieved from database
Data is assigned to a 'DataView' object and assigned to the GridView1 DataSource property.
GridView1.DataBind() is invoked
Miscellaneous conditional logic which removes certain columns from GridView1
An OnClick attribute is added to each row.
So actually, the Page_Load binds the first GridView. The 2nd GridView is the one which contains the ListView which I am having a problem with. This 2nd GridView (the code of which is at the top of the post) is populated on the 'OnRowCommand' event of the 1st GridView, and has a sequence like this:
GetDataForListView
Get data from database
Assign the DataSet containing the data to the DataSource property of the 2nd GridView
Call the DataBind() method
Then, as you can see from the code I posted at the top, I have the OnRowDataBound event which fails to invoke its event in the code-behind.
Ciaran, I replicated the whole scenario and found out the below issue.
Issue: When any event related to either the GridView2 or ListView or the LinkButton is being fired it first hits the Page_load function. In the Page_load function you are not data binding GridView2 and the ListView so apparently they almost vanish and so the Event will not be fired.
Possible Fix:
You need to bind the GridView2 in the Page_load function in order fire those related events and the same goes with the ListView Too.
This fix is a very big one. I am not sure if you could try this.
a. If you are binding the GridView2 depending on the condition generated by the GridView1 click then store those parameters in some hidden field.
b. Have a function named LoadGridView2(parameters) where you bind the GridView2 and the ListView depending on the parameters passed and call this function in the Page_Load function each every time a PostBack is done and pass the stored parameters in the hidden field to the LoadGridView2(parameters)
c. By doing above you can bind the GridView2 according the GirdView1 Click condition and make the GridView2 and ListView available in the PostBack too. So now the event could be fired.
Let me know in case of any queries.
LinkButton has OnCommand, ListVIew has OnItemCommand. So the name isn't correct. OnCommand only fires if the LinkButton has a CommandName set. And also, the repeater may swallow the button's command argument. Certain controls do that because of the way events bubble up to the UI.
<asp:LinkButton ID="linkButton" Runat="Server" OnCommand="DoSomething"
CommandName="DoSomething"
CommandArgument='<%# Eval("ROW_NUM") %>' Text='<%# Eval("FILE_NAME") %>'>
</asp:LinkButton>
Or Try adding:
<asp:ListView .. OnItemCommand=".." />
And then do:
void DoSomething(Object Sender, ListViewCommandEventArgs e) {
// Do something
}
Your button would still need to set a command name like:
<asp:LinkButton .. CommandName="DoSomething" />
I am doing a project in .net with c#. in that there is a registration form of new users into the site. admin should approve the registration. for that I'm using a GridView. How to find out the selected row in the grid view?
Use the GridView.SelectedRow property.
Alternatively, you can get the index of the selected row with the GridView.SelectedIndex property.
are you perhaps referring to a DATAGRIDVIEW?
if so, to find the content of a certain column of the selected row
datagridviewname.item(0, datagridviewname.currentrow.index).value
where 0 = first column of your datagrid
Use following gridview property>
gvTradeFile.SelectedRows[0].Cells[10].Value.ToString();
Hope this will help you.
Normally I use RowCommand for this type of thing:
<asp:GridView runat="server" id="gvUsers" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="username" HeaderText="Username" />
<asp:BoundField DataField="dateregistered" HeaderText="Date" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" id="lnkApprove" CommandName="Approve" CommandArgument='<%# Eval("userid") %>' Text="Approve"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" id="lnkDeny" CommandName="Deny" CommandArgument='<%# Eval("userid") %>' Text="Deny"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now you need to pass instructions through on RowCommand...
private void gvUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName)
{
case "Approve":
// Executes code to update the users table,
// setting the approved flag to true
// Usage: ApproveUser(integer userid);
ApproveUser(e.CommandArgument);
break;
case else:
// do whatever if the user registration wasn't approved
break;
}
}
The switch is a good idea in case you need to do a few things with the data here. It evaluates the primary key value for the row (in this case, that's the value of the userid column in the database) for the selected row (automatically determined when you click the link) along with the CommandName to tell it what to do with that information.
Hope this helps.