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.
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.
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");
}
}
I have been trying to write this simple logic of deleting a row from the gridview and from the SQL database of the selected row, but keep getting a null reference to cell, which has the primary key [ID] in a field.
Here's my html:
<asp:GridView ID="grvInventoryEdit" runat="server" BackColor="White" onrowdeleting="grvInventoryEdit_RowDeleting"
onrowediting="grvInventoryEdit_RowEditing"
onrowupdating="grvInventoryEdit_RowUpdating">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:CommandField ShowDeleteButton="True" /><asp:TemplateField HeaderText="Id">
<ItemTemplate>
<%#Eval("No")%>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>........ </Columns> </asp:GridView>
And my back-end code for rowdeleting event is :
protected void grvInventoryEdit_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
TextBox id = (TextBox)grvInventoryEdit.Rows[e.RowIndex].FindControl("txtEditNo");
Asset asset = db.Assets.Single(a => a.No == Convert.ToInt32(id));
db.Assets.DeleteOnSubmit(asset);
db.SubmitChanges();
binddata();
}
and when the event fires, this is what i am seeing while debugging:
I am not sure why i am getting a null value ,though, there is a value for that cell.
Could you tell me what i am doing wrong ?
Regards,
Might be it is due to the readonly property of textbox, not suer.
If you want to use the image button for edit and delete then use
protected void ibtnDelete_Click(object sender, ImageClickEventArgs e)
{
GridViewRow gvRow = (GridViewRow)((ImageButton)sender).NamingContainer;
Int32 UserId = Convert.ToInt32(gvUsers.DataKeys[gvRow.RowIndex].Value);
// delete and hide the row from grid view
if (DeleteUserByID(UserId))
gvRow.Visible = false;
}
For complete code see
You are passing TextBox object instead instead of Text property of TextBox
Asset asset = db.Assets.Single(x=>x.No == Convert.ToInt32(id.Text));
and your TextBox is also coming null means it's unable to find it in GridView, try like this:
TextBox id = e.Row.FindControl("txtEditNo");
Also see this CodeProject article to understand how to use ItemTemplate and EditItemTemplate
why are you adding a second commandfield instead of just enabling the delete button on the existing one.
if you are using a command field you should be supplying an compatible datasource that provides Delete functionality
if you're "rolling your own" delete functionality then just use a regular Button control and supply a CommandName and CommandArgument, such as CommandName="MyDelete" CommandArgument=<row number> where <row number> is supplied via GridView RowDataBound() event.
Regardless of how you choose to implement Delete you should be placing the key field in the GridView DataKeys Property and not as a field within each row. This will make obtaining the PK far easier than what you are trying to do
I guess, in my HTML, i have only the value that's bound to the item, is being displayed, and there are no textboxes in my <ItemTemplate>, hence, it pulls null value. Whereas, in my <EditItemTemplate> there is a textbox, which can pull the value from the cell.
So I changed my HTML to this:
<asp:TemplateField HeaderText="Id">
<ItemTemplate>`<asp:label runat="server" ID="lblEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
and no change in my codebehind, and this resolved the issue.
I have usedgridView for update and delete data. But I'm getting
"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index" error while updating.
There is no problem in your jquery datetimepicker
Problem seems to be in :
GridViewRow row = GridView1.Rows[e.RowIndex];
Simply take separate link buttons for edit and delete as:
<asp:TemplateField HeaderText="Edit" ItemStyle-Width="150">
<ItemTemplate>
<asp:linkbutton id="lnkEdit" runat="server" CommandName="Edit" Text="Edit"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete" ItemStyle-Width="150">
<ItemTemplate>
<asp:linkbutton id="lnkDelete" runat="server" CommandName="Delete" Text="Delete" />
</ItemTemplate>
</asp:TemplateField>
I can see you are using dropdownlist for copy_id so it is better to use the below code to find the dropdownlist and fetch value from it.
DropDownList lblCopyDdl= (DropDownList )GridView1.Rows[e.RowIndex].FindControl("lblCopyId");
int Copy_Id = Convert.ToInt32(lblCopyDdl.selectedvalue);
Recommendation::
Better if you use the same code as mentioned above for other fields for getting value..
for eg
int Borrower_Id = Convert.ToInt32((TextBox)GridView1.Rows[e.RowIndex].FindControl("txtBorrowerId").Text);
Update::
If it not works then do check your e.RowIndex as mentioned in Ángel Di María's answer.
Update 2
try to fetch the date field like this
DateTime Date_Borrowed = Convert.ToDateTime((TextBox)GridView1.Rows[e.RowIndex].FindControl("txtDateBorrowed").Text);
and
DateTime Date_Returned= Convert.ToDateTime((TextBox)GridView1.Rows[e.RowIndex].FindControl("txtDateReturned").Text);
It seems that you are trying to read a cell value using index but there is no data element at that position. Suggest you to do debug and increment index value in your collection in watch window and observe data
If I have this <asp:ButtonField runat="server" DataTextField="Name" CommandName="GetName"></asp:ButonField> Within a GridView. Is there any way to retrieve the DataTextField (Name) from the OnRowCommand method?
<asp:GridView ID="GridView1" runat="server"
AllowPaging="True" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource_Names"
DataKeyNames="ID,ModuleId" OnRowCommand="ChangeName">
Or alternatively, is there any way to make CommandName into an attribute where the command is dynamically entered based on given data, similar to the difference between DataTextField vs TextField.
I added <asp:BoundField DataField="Name" /> Then you can retrieve it using the same method here: GridView.onRowCommand Method
All I need to do now is find out a way to hide the field. If anyone knows how to, please let me know. Visible="false" gets rid of the field all together...
Not really sure if this is the best way, but it works:
Make your column a templatefield and bind the name value to a asp:hiddenfield control:
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField ID="hfName" runat="server" Value='<%# Eval("Name") %>'>
</asp:HiddenField>
</ItemTemplate>
</asp:TemplateField>