How do I access the underlying DataTable in an ASP.NET GridView - asp.net

I have a paginated GridView on an ASP.NET page. In the DataBound event of the GridView control, I am attempting to update the OnClick event of each cell in the row to window.open() a new page using a field in the underlying DataTable that is not displayed in the GridView. However, the GridView DataSource propety is null, as is the GridViewRow DataItem property. The GridView's DataKeys has a Count of 0. The paginated DataSet has 20 rows and is being rendered properly, I just can't find the underlying data to pull the ID needed for the window.open() call.
I have followed asp.net's guide when constructing my page:
Creating a data access layer
Creating a business access layer
Displaying Data with ObjectDataSource
So I have a DAL -> BLL -> ObjectDataSource -> GridView. The ID column is being hidden in the GridView:
<asp:GridView ID="pdfdocuments" runat="server" AllowPaging="True"
AutoGenerateColumns="False" DataSourceID="pdfods" PageSize="20"
ondatabound="pdfdocuments_DataBound">
<PagerSettings Mode="NumericFirstLast" />
<Columns>
<asp:BoundField DataField="pdf_id" HeaderText="pdf_id" InsertVisible="False"
ReadOnly="True" SortExpression="pdf_id" Visible="False" />
...
</Columns>
<HeaderStyle BackColor="#FFCC99" />
<AlternatingRowStyle BackColor="#FFFFCC" />
</asp:GridView>
How do I access the pdf_id value in the underlying DataTable?

Try accessing GridView.DataSourceObject in the RowDataBound event.
Unless there is some requirement to use javascript window.open it is probably better to use an anchor tag with a target like the following code:
<asp:GridView ID="GridView1" runat="server" DataSourceID="ODS1"
OnRowDataBound="GridView1_RowDataBound" AutoGenerateColumns="False">
<Columns>
<asp:HyperLinkField DataTextField="FieldName" DataNavigateUrlFields="FieldID" DataNavigateUrlFormatString="somePage.aspx?id={0}" Target="_blank" />
</Columns>
</asp:GridView>
If you have to execute JavaScript you can still do it without accessing the underlying DataSourceObject directly using a TemplateField:
<asp:GridView ID="GridView1" runat="server" DataSourceID="ODS1"
OnRowDataBound="GridView1_RowDataBound" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<a href='javascript:window.open(<%# Eval("FieldID") %>);'><%#Eval("FieldName")%></a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

I agree with D-Mac to use RowDataBound event. But instead of using GridView.DataSourceObject try to access the row's DataItem property.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataRowView rowView = e.Row.DataItem as DataRowView;
if (rowView != null)
{
//Check if the execution reach this pont
object pdf_id = rowView["pdf_id"];
}
}
You can find an example here

Related

How to delete a row in a dynamically generating grid view?

Hello Respected sirs,
I am generating a shopping cart like ordering system, in which i add/bind the productname, productprice, and productquantity from DataTable to GridView.
I have Added an ImageButton to the gridview only for deleting the selected row.
I also know that we can not delete a row from a dynamically generated grid view. so i placed a code in the ImageButton Click event that deletes the row from DataTable (Which is STATIC during the whole process) and again binds the Data With GridView.
Please note that i hv already once bind the data with gridview in my "BTN_ADD TO CART_Clicked".
Here is my code snippet,
protected void gvorderlist_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
int index = Convert.ToInt32(e.CommandArgument);
DataRow row = dt.Rows[index];
dt.Rows.Remove(row);
gvorderlist.DataSource = dt;
gvorderlist.DataBind();
}
}
and ASP code is,
<asp:GridView ID="gvorderlist" runat="server" CellPadding="4"
ForeColor="#333333" GridLines="None" AllowPaging="True" PageSize="5"
onpageindexchanging="gvorderlist_PageIndexChanging"
onrowcommand="gvorderlist_RowCommand">
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="Cancel Order" ShowHeader="False">
<ItemTemplate>
<asp:ImageButton ID="ImgbtnCancelOrder" runat="server" CausesValidation="false"
ImageUrl="~/images/cross.PNG" OnClientClick="Javascript: return confirm('Aap Chutiye hai');" CommandName="Delete"
CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I am getting an Error which says : The GridView 'gvorderlist' fired event RowDeleting which wasn't handled.
Any help will be appreciated...
Thank You
The error explains everything. You need todefine the event method for OnRowDeleting in markup:
<asp:GridView ID="gvorderlist" runat="server" CellPadding="4"
ForeColor="#333333" GridLines="None" AllowPaging="True" PageSize="5"
onpageindexchanging="gvorderlist_PageIndexChanging"
onrowcommand="gvorderlist_RowCommand" OnRowDeleting="gvorderlist_RowDeleting">
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="Cancel Order" ShowHeader="False">
<ItemTemplate>
<asp:ImageButton ID="ImgbtnCancelOrder" runat="server" CausesValidation="false"
ImageUrl="~/images/cross.PNG" OnClientClick="Javascript: return confirm('Aap Chutiye hai');" CommandName="Delete"
CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And add an empty method in the code:
protected void gvorderlist_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
// No need to implement code here
}
The attributes for the GridView are case-sensitive, so change onrowcommand to OnRowCommand and see if that fires when you click the delete button. If not, you'll need to define OnRowDeleting explicitly. (Also change the capitalization of onpageindexingchange)
Give Command Name=D instead of Delete. It searches for Row_Deleting event when Command Name =Delete.

Using RowEditing event to update CheckBoxList in Gridview EditTemplate, based on value in ItemTemplate

I have a gridview 'gvAccounts' with a column 'Entitlements' (amongst others). Each Entitlements cell contains another gridview 'gvEntitlements', with a list of entitlements for each account (each row in gvAccounts is an account).
In the EditTemplate for the Entitlements cell, I have a CheckBoxList 'cblEntitlements', which is filled with all of the available entitlements.
When I click Edit, I want the cblEntitlements to only have the those entitlements checked which appear in gvEntitlements. I tried a bunch of things in the RowEditing event and nothing worked (lots of null reference errors when using .FindControl on the row), so I thought I would just ask what the best way to do this is, rather than paste my failed attempts.
Thanks!
Markup:
<asp:GridView
ID="gvAccounts"
runat="server"
DataSourceID="AccountsObjectDataSource"
AllowSorting="True"
AutoGenerateColumns="False"
DataKeyNames="CorpID,AppKey"
Width="100%"
OnRowDataBound="gvAccounts_RowDataBound"
OnRowEditing="gvAccounts_RowEditing"
EnableModelValidation="True" >
<Columns>
<asp:TemplateField
HeaderText="Entitlements"
SortExpression="Entitlements">
<ItemTemplate>
<asp:GridView
ID="gvEntitlements"
DataKeyNames="EntitlementID"
runat="server"
ShowHeader="False"
BorderStyle="None"
EmptyDataText="common"
GridLines="None"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField
DataField="EntitlementID"
Visible="false" />
<asp:BoundField
DataField="Entitlement"/>
</Columns>
</asp:GridView>
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBoxList
ID="cblEntitlements"
runat="server"
DataSourceID="cblObjectDataSource"
DataTextField="Entitlement"
DataValueField="EntitlementID"
RepeatColumns="2"
RepeatDirection="Horizontal">
</asp:CheckBoxList>
<asp:ObjectDataSource
ID="cblObjectDataSource"
runat="server"
SelectMethod="GetAppEntitlements"
TypeName="CMRPWebApp.Business.CMRPControllerApps">
<SelectParameters>
<asp:ControlParameter
ControlID="DropDownList1"
Name="AppKey"
PropertyName="SelectedValue"
Type="Int32"/>
</SelectParameters>
</asp:ObjectDataSource>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource
ID="AccountsObjectDataSource"
runat="server"
SelectMethod="GetUsersForApp"
TypeName="CMRPWebApp.Business.CMRPControllerApps"
<SelectParameters>
<asp:ControlParameter
ControlID="DropDownList1"
Name="AppKey"
PropertyName="SelectedValue"
Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
code-behind:
protected void gvAccounts_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//for each row, run a query for that appkey + corp ID to retrieve the entitlements for that account.
System.Collections.Specialized.IOrderedDictionary datakeyNames = gvAccountsApp.DataKeys[e.Row.RowIndex].Values;
string corpID = datakeyNames["CorpID"].ToString();
int appKey = Convert.ToInt32(datakeyNames["AppKey"]);
if ((e.Row.FindControl("gvEntitlements") as GridView) != null)
{
GridView gv = e.Row.FindControl("gvEntitlements") as GridView;
gv.DataSource = CMRPControllerApps.GetAccountEntitlements(corpID, appKey);
gv.DataBind();
}
}
}
protected void gvAccounts_RowEditing(object sender, GridViewEditEventArgs e)
{
// ?
}
From my understanding of your question, you want the edit template to show all entitlements, with only the entitlements that belong to the specific account being checked.
A couple of things that I noticed:
In your code behind, it looks like you are binding something named GridView1 to the list of entitlements for a specific account. I don't see anything named that in your code.
Are you binding to the gridview twice? In your markup I see that you are setting the datasource to cblEntitlements. Is this the specific problem you are facing?
I apologize if I am missing the point here, just a little confused.

ASP.net GridView: get LinkItem's row

I want to show "Delete" link in GridView to registred users, therefore I am using templateField:
<asp:GridView ID="GridView1" runat="server" AllowSorting="True" OnSorting="GridView_Sort">
<Columns>
<asp:TemplateField HeaderText="Control">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" onClick="deleteEntry()" Text="Delete"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now in my deleteEntry() function how can I know anything about the row in which "Delete" link was clicked? How to ge for e.g. rowindex?
You could approach this slightly different. You see, when a control is placed inside a gridview, any event raised from that control raises also the RowCommand on the GridView.
To get what you want you could then add both CommandName and CommandArgument to your LinkButton and then catch it in the GridView's RowCommand.
<asp:LinkButton id="LinkButton1" runat="server" commandName="LinkButtonClicked" commandArgument='Eval("myObjectID")' />
where myObjectID is the name of the ID column of your object you bind the grid to.
Then
void GridView1_RowCommand( object sender, GridViewCommandEventArgs e )
{
if ( e.CommandName == "LinkButtonClicked" )
{
string id = e.CommandArgument; // this is the ID of the clicked item
}
}

ASP.NET Grid View Problem

I have one gridview where I am passing the command argument as gridview row id for the Button I created for every row.
I want to display all the details of that row in the textbox according to the Row clicked.
<asp:GridView ID="gvCategory" runat="server" AutoGenerateColumns="false"
onrowcommand="gvCategory_RowCommand" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblCatId" runat="server" Text='<%#Eval("categoryId") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblCatName" runat="server" Text='<%#Eval("categoryName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnModify" runat="server" Text="Modify" CommandName="Modify" CommandArgument='<%#Eval("categoryId") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code.....
if (e.CommandName == "Modify")
{
int id = Convert.ToInt32(e.CommandArgument);
// I want the value to assgin for the selected row here
// I was previously fetching the data from database according id,but i want this frim the gridview of selected row.
}
I wrote a quick example of how to do what you're trying to do. It works for me.
The Example Solution
Default.aspx
<asp:GridView ID="myGridView" runat="server"
AutoGenerateColumns="False"
DataSourceID="StudentsDS"
DataKeyNames="ID"
OnRowCommand="myGridView_RowCommand"
OnSelectedIndexChanged="myGridView_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True"
SortExpression="ID" />
<asp:BoundField DataField="FullName" HeaderText="FullName"
SortExpression="FullName" />
<asp:BoundField DataField="ClassID" HeaderText="ClassID"
SortExpression="ClassID" />
<asp:CommandField ShowSelectButton="True" SelectText="Modify" />
</Columns>
</asp:GridView>
<asp:TextBox ID="txtStudent" runat="server" />
<asp:SqlDataSource ID="StudentsDS" runat="server"
ConnectionString="<%$ ConnectionStrings:Sandbox %>"
SelectCommand="SELECT * FROM Student"
/>
Default.aspx.cs
protected void myGridView_RowCommand(object sender, GridViewCommandEventArgs e) {
if (e.CommandName == "Select") {
// do something here if you want, although not necessary
}
}
protected void myGridView_SelectedIndexChanged(object sender, EventArgs e) {
// show "FullName" field of selected row in textbox
txtStudent.Text = myGridView.SelectedRow.Cells[1].Text;
}
How It Works
Upon clicking "Modify" in a row, the textbox updates to show the FullName field of the selected row.
The important part is that instead of a TemplateField, use a CommandField with ShowSelectButton="True". Then do what you need to do in the SelectedIndexChanged event handler. Note that the SelectText of the CommandField is set to "Modify" as you desired. You can also set the ButtonType property of the CommandField to be button, image, or link.
Making It Better
I would also advise that instead of using a SqlDataSource as I have, you use an ObjectDataSource so that you can do something like
protected void myGridView_SelectedIndexChanged(object sender, EventArgs e) {
MyModelObject o = myGridView.SelectedRow.DataItem as MyModelObject;
txtStudent.Text = o.MyProperty;
}
You may also consider wrapping your GridView in an UpdatePanel to prevent full postbacks / page refreshes.
After you have the lineID, you select that line, and then you have the CategoryID on selected value
int iTheIndexNow = Convert.ToInt32(e.CommandArgument);
// select that line to see it visual as selected, and get the value on next line
gvCategory.SelectedIndex = iTheIndexNow;
// here is your categoryID that
//you can use to open your database with and get the text
gvCategory.SelectedValue // == categoryID
On GridView you must have set your KeyID
<asp:GridView DataKeyNames="categoryId" .... >

GridView ASP.NET Sorting

I have an ASP.NET GridView that just won't sort! I'm sure that I am missing something pretty obvious.
Page.aspx
<asp:GridView ID="TimeAwayGridView" runat="server" AutoGenerateSelectButton="False"
AutoGenerateEditButton="False" AutoGenerateDeleteButton="False" AllowPaging="False"
AllowSorting="True" CssClass="gridview" OnSorting="TimeAwayGridView_Sorting">
<Columns>
<asp:BoundField DataField="Description" HeaderText="Description" SortExpression="Description" />
<asp:BoundField DataField="Hours" HeaderText="Hours" SortExpression="Hours" />
</Columns>
<EmptyDataTemplate>
There are currently no items in this table.
</EmptyDataTemplate>
</asp:GridView>
Page.aspx.cs
protected void TimeAwayGridView_Sorting(object sender, GridViewSortEventArgs e)
{
}
Asp.Net Datagrip provides you with sorting event, and name of the column that was clicked in GridViewSortEventArgs, but you have to provide you own sort implementation in TimeAwayGridView_Sorting function. Meaning you should sort your datasource and rebind the datagrid.

Resources