Getting the DataKey Value in ASP.NET GridView on Button command event - asp.net

Gridview is configured:
<asp:GridView ID="gvApptList" runat="server" CssClass="fullwidth" AutoGenerateColumns="False" DataKeyNames="AppointmentID">
<Columns>
<asp:BoundField DataField="Designer" HeaderText="Designer" SortExpression="Designer" />
<asp:BoundField DataField="AppointmentDTM" HeaderText="Appointment Date" SortExpression="AppointmentDTM" DataFormatString="{0:MM-dd-yyyy hh:mm tt}" />
<asp:BoundField DataField="Status" HeaderText="Status" SortExpression="Status" />
<asp:BoundField DataField="Disposition" HeaderText="Disposition" SortExpression="Disposition" />
<asp:BoundField DataField="AppointmentNotes" HeaderText="Appointment Notes" SortExpression="AppointmentNotes" />
<asp:ButtonField ButtonType="Button" CommandName="viewAppointment" Text="View" />
</Columns>
</asp:GridView>
When I click the "View" button, the gvApptList_RowCommand fires off. COde for it is:
If e.CommandName = "viewAppointment" Then
Dim tApptID As Long
gvApptList.SelectedIndex = e.CommandArgument
If IsNumeric(gvApptList.DataKeys(e.CommandArgument).Value) Then
tApptID = gvApptList.SelectedDataKey.Value
Else
Exit Sub
End If
tbAppointmentID.Text = tApptID
DisplayInfo()
End If
The gvApptList.DataKeys(e.CommandArgument).Value always comes back as nothing. What am I missing here? I have this exact sale code working on other pages.

Pertinent to your task, the correct syntax using DataKeys in ASP.NET GridView control is shown below (re: http://www.codeproject.com/Tips/225352/Nesting-GridView-control-in-ASP-NET, written in C#):
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get data key from selected row
s.SelectParameters[0].DefaultValue =Convert.ToString(((GridView)sender).DataKeys[e.Row.RowIndex].Values["AppointmentID "]);
}
}
You should obtain the reference to the Row corresponding to the command Button clicked, then extract the DataKeys value from that Row. Also, make sure that underlying DataSource contains AppointmentID field in its SELECT query.
Pertinent to your case it may look like the following (see Listing 2)
Listing 2.
protected void ViewButton_OnClick(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow row = btn.NamingContainer as GridViewRow;
string strID = gvApptList.DataKeys[row.RowIndex].Values["AppointmentID"].ToString();
int intID;
if (String.IsNotNullOrEmpty(strID)
{
intID = int.Parse(strID);
}
}
or you may use TryParse(), Convert(), etc.
Hope this may help.

Related

ASP.NET Gridview Selected Index Changed not firing

This has been asked quite a few times, but still.
In GridView is defined event OnSelectedIndexChanged. My expectation is, that if I click on a row in gridview, the event will be fired. I managed to do the same with image buttons, but I want the entire row to be clickable.
<asp:GridView runat="server" ID="gameGrid" PageSize="20" PagerSettings-Mode="NextPreviousFirstLast"
OnRowDataBound="GameGrid_RowDataBound" OnPageIndexChanging="GameGrid_PageIndexChanging"
AutoGenerateColumns="false" CssClass="table table-hover table-striped" AllowPaging="True"
AllowSorting="True" ShowHeaderWhenEmpty="True" OnSelectedIndexChanged="gameGrid_SelectedIndexChanged">
<Columns>
<asp:BoundField HeaderText="Game Id" DataField="ID_Game" SortExpression="ID_Game" />
<asp:BoundField HeaderText="Player" DataField="Email" SortExpression="Email" />
<asp:BoundField HeaderText="Finshed" SortExpression="Finished" />
<asp:BoundField HeaderText="Started At" SortExpression="CreateDate" />
<asp:BoundField HeaderText="Last Updated At" SortExpression="LastUpdate" />
</Columns>
</asp:GridView>
I was assuming that if I define an EventHandler in CodeBehind, it will be fired.
protected void gameGrid_SelectedIndexChanged(object sender, EventArgs e)
{
int i = 0;
}
Why is this event not firing?
I would like to redirect the user on a different page with an ID parameter in URL. Should I do something different?
First, set the AutoGenerateSelectButton property to true in the GridView. This will generate a LinkButton. Now in the RowDataBound event do the following.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//check if the row is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//find the select button in the row (in this case the first control in the first cell)
LinkButton lb = e.Row.Cells[0].Controls[0] as LinkButton;
//hide the button, but it still needs to be on the page
lb.Attributes.Add("style", "display:none");
//add the click event to the gridview row
e.Row.Attributes.Add("onclick", Page.ClientScript.GetPostBackClientHyperlink((GridView)sender, "Select$" + e.Row.RowIndex));
}
}
You could add the OnClick event to the row without showing the SelectButton, but then you would to turn off EnableEventValidation as seen here How to create a gridview row clickable?

Get clicked cell in gridview asp.net

I got gridview that I fill with data from my database. I would like to catch an event of click and to get attributes of the cell row and column.
all I found is row click that I can get the row clicked.
also, if there is other component to deploy the data and can get me the cell click event is good enough for me.
HTML:
<div class="grid">
<asp:GridView ID="HistoricGrid" runat="server"></asp:GridView>
</div>
C#
DBconnection db = new DBconnection();
string strtable = "select * from StudentVisit";
DataTable dt = db.ReadDataTable(strtable);
HistoricGrid.DataSource = dt; HistoricGrid.DataBind();
thanks for the help,
Moshe
You should try this.
<asp:GridView ID="GridView1" AutoGenerateColumns="False" ShowHeader="True" runat="server" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField HeaderText="Value" DataField="ItemValue" ReadOnly="true" />
<asp:BoundField HeaderText="Text" DataField="ItemText" ReadOnly="true" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
aspx.cs file
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if ( e.Row.RowType == DataControlRowType.DataRow )
{
LinkButton linkButton = (LinkButton)e.Row.FindControl("LinkButton1");
if (linkButton != null)
{
linkButton.Attributes.Add("onclick", "window.open('someURL'); return false;");
}
}
}
You can use below code
private void gv_Cell_Click(object sender, GridViewCellEventArgs e)
{
int cellindex=e.CellIndex;
int rowindex =e.rowindex;
var value = gv.Rows[rowindex].Cells[cellindex].value;
}

itemTemplate item id not existing in code behind

I am trying to create textboxes that are equal to the number of rows in grid view (databound from db). here is my markup
<asp:GridView ID="quizGrid" runat="server" CssClass="Grid" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="admissionNO" HeaderText="Admission NO"/>
<asp:BoundField DataField="studentName" HeaderText="Name" />
<asp:TemplateField>
<ItemTemplate>
<asp:Textbox runat="server" ID="marks" > </asp:Textbox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
but when i use the marks in code behind it says
quizGrid_marks_0 does not exists in the current context
what im doing wrong here?
You can't access your textbox like that in code behind file, rather you need to find them in RowDataBound event like this:-
protected void quizGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
TextBox marks = (TextBox)e.Row.FindControl("marks");
txtMarks.Text = "Test";
}
}
Edit:
Okay, suppose you have a button btnGetData with button click event as btnGetData_Click, then you can find the textbox text by looping through the gridview rows like this:-
protected void btnGetData_Click(object sender, EventArgs e)
{
GridView quizGrid = (GridView)Page.FindControl("quizGrid");
foreach (GridViewRow row in quizGrid.Rows)
{
TextBox marks = (TextBox)row.FindControl("marks");
}
}

ASP.NET GridView Data which i set on RowDatabound event loses after post back

I have an asp.net page where i have a gridview control which bind data from a DataTable.
In my 5 th column of the grid i am showing a Radio button list which has 2 Radio button items (Yes or No). For Some rows i will not show the RadioButton control, if the 4 th column cell value is empty. It works fine.But in my button click event (postback), the Grid is showing the Radio button list for those cells which was not shown initially. I have enabled ViewState for page and Control
This is my code
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns=false
DataKeyNames="RequestDetailId" ondatabound="GridView1_DataBound" EnableViewState ="true" AllowPaging=false
onrowdatabound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="RequestDetailId" HeaderText="Request Detail Id" />
<asp:BoundField DataField="Item" HeaderText="Item" />
<asp:BoundField DataField="Status" HeaderText="Status" />
<asp:BoundField DataField="NewOffer" HeaderText="New Offer" />
<asp:TemplateField HeaderText="Your Response" ItemStyle-CssClass="radioTD">
<ItemTemplate>
<asp:RadioButtonList ID="radioList" runat="server">
<asp:ListItem Text="Yes" Value="Accept"></asp:ListItem>
<asp:ListItem Text="No" Value="Reject"></asp:ListItem>
</asp:RadioButtonList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
in code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadItemDetails();
}
}
private void LoadItemDetails()
{
DataTable objDt= GetGridDataSource();
if (objDt.Rows.Count > 0)
{
GridView1.DataSource = objDt;
GridView1.DataBind();
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(String.IsNullOrEmpty (e.Row.Cells[3].Text.Trim())||(e.Row.Cells [3].Text ==" "))
{
e.Row.Cells[4].Text = "";
}
}
My results are
Before Postback
After Postback
How do i maintain the content after postback ? Thanks
The problem is that you are setting the Text of the GridView table cell to an empty string rather than setting the visibility of the RadioButtonList control to false.
Clearing the Text property is removing the markup for the RadioButtonList on the first load, but on postback the RowDataBound event is not fired and the RadioButtonList control is recreated and displayed again.
To avoid this you could find the control and set its visibility to false, this will then be remembered across postbacks.
Try the following:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (String.IsNullOrEmpty(e.Row.Cells[3].Text.Trim()) || (e.Row.Cells[3].Text == " "))
{
RadioButtonList radioList = (RadioButtonList)e.Row.FindControl("radioList");
radioList.Visible = false;
}
}
Hope this helps.
you can do something like this ..
from the description of the problem. it sounds as if you are doing the databinding in the code behind. in such case asp.net does not preserve the datasource in the viewstate for you. try retrieving the data and storing it in the ViewState hashtable object with something like
ViewState["GridviewData"] = GridviewData
and retreiving it from there between postbacks

GridView Paging Issue

I have a very simple GridView on one of my pages with the following markup on my .aspx page:
<asp:GridView ID="gvNews" runat="server" AutoGenerateColumns="false" AllowPaging="true"
AllowSorting="true" DataKeyNames="NewsID,VersionStamp" OnPageIndexChanging="gvNews_PageIndexChanging"
OnRowCreated="gvNews_RowCreated">
<Columns>
<asp:BoundField HeaderText="News Title" DataField="NewsTitle"
SortExpression="NewsTitle" ReadOnly="true" />
<asp:BoundField HeaderText="News Content" DataField="NewsContent"
SortExpression="NewsContent" ReadOnly="true" />
<asp:BoundField HeaderText="Posted Date" DataField="InsertedDate"
SortExpression="InsertedDate" ReadOnly="True" />
<asp:BoundField HeaderText="InsertedBy" DataField="InsertedBy" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lbEdit" runat="server" Text="Edit" CommandName="Select" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Below is the code on my .cs page:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadGrid();
}
}
private void LoadGrid()
{
gvNews.DataSource = GetNews();
gvNews.DataBind();
}
protected void gvNews_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
}
protected void gvNews_RowCreated(object sender, GridViewRowEventArgs e)
{
e.Row.Cells[3].Visible = false;
}
On the RowCreated event I am trying to hide the InsertedBy column in the gridview. This code works fine when AllowPaging is set to flase. But when the AllowPaging is set to true I get the following error in the RowCreated event handler:
Specified argument was out of the range of valid values.
Parameter name: index
What could be the reasons for this behavior?
You need to write your code like this:
protected void gvNews_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[3].Visible = false;
}
}
With a GridView there are different types of rows that might get created and they will have different numbers of cells, but the RowCreated event will fire for all rows, so you need to limit your logic to only data rows in this case.
From what you have posted your hard coded value of 3 in the RowCreated event seems like the problem. Enable tracing on the page and see what you get. BTW the pager next->prev links also cause postback and in PageLoad u are only loading grid if its not a postback which it is when u try to go for next page and the row created is fired.

Resources