Grid OnDataItemBound Event - c#

What should go inside this method? I have a grid displaying results from my SQL Query --- but the grid never populates. The grid is created using HTML and this is how my OnDataItemBound event reads....but what should go here?
protected void dtgfourfiveseven_OnItemDataBound(object sender, DataGridItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
}
}
This is my html I am using to create the grid
<asp:DataGrid runat="server" ID="dtgfourfiveseven" AutoGenerateColumns="false" CssClass="DataGrids"
GridLines="Both" ShowFooter="true" Visible="false" OnItemDataBound="dtgfourfiveseven_OnItemDataBound">
<ItemStyle CssClass="row" />
<FooterStyle CssClass="DataGridFooters" />
<HeaderStyle CssClass="DataGridHeaders" />
<Columns>
<asp:BoundColumn DataField="Employee Name" HeaderText="Employee Name" ItemStyle-Width="100px"></asp:BoundColumn>
<asp:BoundColumn DataField="Eligible For Rehire" HeaderText="Eligible For Rehire" ItemStyle-Width="50px"></asp:BoundColumn>
<asp:BoundColumn DataField="Not Eligible For Rehire" HeaderText="Not Eligible For Rehire" ItemStyle-Width="50px"></asp:BoundColumn>
</Columns>

In my opinion the OnDataItemBound event is not what is preventing the data from displaying. Either your query is returning 0 rows, or you are not binding the query results to the grid. Per MSDN this is what you use the OnDataItemBound event for:
Use the ItemDataBound event to customize the DataGrid control. The ItemDataBound event allows you to access the data before the item is displayed in the control.
An common example of this would be manipulating the data that is returned from your query. I.E. formatting a column to currency.
Thank you for providing the code on how you actually generate your grid through html, but please also provide additional code. Showing how you are actually executing your SQL Query, and how you are actually binding the query results to the grid will allow us to further assist in troubleshooting what is the culprit here.
EDIT ---
A second thought that comes to mind, that may be a quick thing to check is, are you setting the grid.visible = false and not setting it to true later on so the grid is showing your data it is just not showing on the page?

Related

Get Item from GridViewRow ASP.NET

I have a GridView which I Bind a DataSource to it from a SQL Database, the grid has a column with a checkbox in it so I can "select" a few Item in it (Rows actually). What I want here is to do some updates on the Item in each selected rows, but after some search I can't find how to access the Item in a Row, I though DataItem would work, but it's giving me a Null.
Edit: To make it short, I have a GridView which is built from a DataSource, so basically, each rows represent an Object, when I have a checkbox checked in one of the rows, I want to be able to grab the Object related to that Row, what is the easiest way to achieve that?
The DataBinding on Page_Load:
if (!Page.IsPostBack)
{
gvUnusedAccessories.DataSource = currentContext.Items.OfType<Accessory>().Where(ac => ac.Item_Parent_Id == ((PhoneLine)currentItem).Parent.Item_Id);
gvUnusedAccessories.AutoGenerateColumns = false;
gvUnusedAccessories.DataBind();
}
The event when I press the Update Button, It actually browse the rows and if the row has a checked box it's gonna do the update:
protected void btnAddToMobile_Click(object sender, EventArgs e)
{
foreach (GridViewRow row in gvUnusedAccessories.Rows)
{
if(((CheckBox)row.FindControl("chkSelect")).Checked)
{
((Accessory)row.DataItem).PhoneLine_Id = currentItem.Item_Id;
}
}
}
And here's my GridView in the .aspx :
<asp:GridView ID="gvUnusedAccessories" runat="server">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:TemplateField HeaderText="Select">
<ItemTemplate >
<asp:CheckBox ID="chkSelect" runat="server" AutoPostBack="True"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Item_Id" HeaderText="ID" ReadOnly="True"/>
<asp:BoundField DataField="Item_Name" HeaderText="Name" ReadOnly="True"/>
<asp:BoundField DataField="AccessoryModel" HeaderText="Modèle" ReadOnly="True"/>
<asp:BoundField DataField="AccessoryBrand" HeaderText="Marque" ReadOnly="True"/>
</Columns>
</asp:GridView>
Any hint on how to access the Object contained inside a Row?
I know I could actually get the ID and then do a SQL request to my DB, but it seems to be a bit heavy and there must be a better solution.
Unless you're storing the DataSource in ViewState or session once the databinding is done you lose the data source. The DataItem will always be null unless you do this. Because of this I often find myself storing the data source in view state. Of course this means your page size is going to get bigger. The other option as you stated is to requery the data source with some sort of primary key. Depending on your needs I can't say which option is better. I tend to lean towards view state rather than a second DB call since that can be an expensive call to make
Given that you have the AutoPostBack set to true on your asp:checkbox you must update the row as you set the checkbox
So I would suggest you you set event OnCheckedChanged="chkStatus_OnCheckedChanged" on asp:checkbox called chkSelect and then you can only update the selected row and don't have to iterate over the enitre grid.
Here is an example how you can get the row items of the selected checkbox
public void chkStatus_OnCheckedChanged(object sender, EventArgs e)
{
CheckBox chkStatus = (CheckBox)sender;
//now grab the row that you want to update
GridViewRow row = (GridViewRow)chkStatus.NamingContainer;
string cid = row.Cells[1].Text;
bool status = chkStatus.Checked;
//now you can do you sql update here
}

DataGrid and formatting data

I'm new to ASP.NET and don't really understand how to display a table with database data. The data is loaded in an object, where I have a list of objects.
Now I want to show a table with some columns, an image (path created from two fields in the object), an link (passing one field of the object), a textarea (id from object, value from object), a radiobutton (id from object).
How should I do this. I have tried binding a datagrid to the list of objects, and it works. But I don't want to show all data members, and I don't know how to create correct headers and the image and form controls.
ImageDataGridView.DataSource = tradeObj.Images;
ImageDataGridView.DataBind();
To stop the automatic creation of a column for each column in the data source, set:
ImageDataGridView.AutoGenerateColumns = false
Then you need to define a column for each column in the data source that you want to display - depending on the column you may want a bound column (you can control the format) or something more involved.
See http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.datagrid.columns.aspx for a sample and the different column types available
You can spefify your column and header using boundfield
<asp:boundfield datafield="yourColumn"
headertext="theHeaderText"/>
And you need to turn off:
ImageDataGridView.AutoGenerateColumns = false
To format values look at this link at msdn.
You need to use template field to customize your datagrid as per below
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField ShowHeader="True">
<ItemTemplate>
<asp:Image runat="server" ID="Image1"
ImageUrl="Enabled.gif" />
</ItemTemplate>
</asp:TemplateField>
......
......
</Columns>
</asp:GridView>
See this msdn link to work with template field in datagrid
Update
For iterate through every row of gridview you need to handle Rowdatabound event as per below.
protected void gridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
Image imgCtrl = (Image) e.Row.FindControl("imgCtrl");
imgCtrl.ImageUrl = "you can apply any format of url here";
}
}
for more information of Rowdatabound event visit this link
Just set autogenerate to false on your datagrid/gridview control. You can then create a templateField column & drop a label or textbox control inside itemTemplate & bind them like
<asp:Label ID="lblMyColumn" Text="<%# Bind("YourColumnName") %>' runat="server"></asp:Label>
Alternatively you can also drop a boundField & set its properties
<asp:BoundField DataField="YourColumnName" HeaderText="Your Text" SortExpression="YourColumnName" />

Accessing the data or dataItem used to bind a gridview

I have a gridview for which I programmatically set the datasource and databind it to a collection of objects. For each row that is created I then use different methods in the fields to extract the relevant information from the object like this one:
<asp:TemplateField HeaderText="Aliases">
<ItemTemplate>
<%# ( (MyItem)Container.DataItem).Aliases.ToString() %>
</ItemTemplate>
</asp:TemplateField>
My problem is that in the OnRowDeleting method I would preferably like to be able to access that DataItem using e g MyGridView.Rows[e.RowIndex].DataItem or in other way. But I can’t find how to configure the Gridview to retain the DataItem. Is it possible to access the DataItem used and how would I configure it to do it? If that’s not possible can I access the values that are bind by the methods? Or do I have to go with plan B and rewrite the datasource object collection to a datatable and then use datakeysnames?
MyGridView.Rows[e.RowIndex].DataItem should generally work but I guess that you are probably relying the view-state for retaining grid data on post-backs. In such case, you will get the DataItem property as NULL.
Work-around can be to always re-bind the grid with actual data in each postback early in page life cycle (say page_load).
However, in your case, you can very well use DataKeyNames. Contrary to your belief, you don't need a DataTable for this property to work. For example, if your class has property named ItemId indicating the key for your object then you can use DataKeyNames="ItemId" in the markup and refer it in OnRowDeleting using Keys property of event arguments.
According to MSDN:
"The DataItem property is only available during and after the RowDataBound event of a GridView control."
Therefore, access the DataItem in the RowDataBound event:
Lets say you bind a List(Of Vehicle) to the grid:
Dim vehicles As List(Of Vehicle) = Vehicle.GetAll()
gvVehicles.DataSource = vehicles
gvVehicles.DataBind()
In the RowDataBound event access the DataItem:
Protected Sub gvVehicles_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim veh As Vehicle = TryCast(e.Row.DataItem, Vehicle)
If Not veh Is Nothing Then
Dim chkBox As CheckBox = CType(e.Row.FindControl("chkSelect"), CheckBox)
chkBox.Checked = True
End If
End If
End Sub
I'm aware this is very dated question at this point - however, I've just run into a similar issue and none of these answers resolved the issue; so I figured I'd post an alternative solution. In my scenario, the issue was on the OnSelectedIndexChanged event. So, it should theoretically hold true for OnRowDeleting but not necessarily on OnRowDeleted (depending on where exactly in the process the row is deleted).
My solution was to simply add a HiddenField for the data that I didn't want to be visible in the GridView, for example:
<asp:GridView ID="gvTutorGroups" runat="server" AutoGenerateColumns="False" DataSourceID="sqlTutorGroups" DataKeyNames="TTGP_Group_Code" AllowPaging="True" PageSize="8" EmptyDataText="You have no tutor groups to display." Style="margin: 0 auto; width: 870px;" OnRowDataBound="gvTutorGroups_RowDataBound" OnSelectedIndexChanged="gvTutorGroups_SelectedIndexChanged">
<Columns>
<asp:TemplateField >
<ItemTemplate>
<asp:HiddenField runat="server" ID="hfTTGPISN" Value="<%# Eval("TTGP_ISN") %>" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="TTGP_Group_Code" HeaderText="TG Code" />
<asp:BoundField DataField="PRPH_Title" HeaderText="Name" />
<asp:BoundField DataField="TTGP_Start_Date" HeaderText="Start Date" DataFormatString="{0:d}" />
<asp:BoundField DataField="TTGP_End_Date" HeaderText="End Date" DataFormatString="{0:d}" />
</Columns>
</asp:GridView>
Then I just used the FindControl method to access that field, like so:
protected void gvTutorGroups_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (GridViewRow row in gvTutorGroups.Rows)
{
if (row.RowIndex == gvTutorGroups.SelectedIndex)
{
row.CssClass = "rowSelected";
DataRowView dataItem = (DataRowView)row.DataItem;
HiddenField hfTGIsn = (HiddenField)this.Parent.FindControl("hfTGisn");
hfTGIsn.Value = ((HiddenField)row.FindControl("hfTTGPISN")).Value;
}
else
{
row.CssClass = "";
}
}
}
It's not an ideal solution, but it works.

ASP.NET CheckBoxField - setting value question

I trying to pass some values that the user selects but I am unable to set the CheckBoxField in my gridview.
Could someone please let me know how to do this?
Here is my code so far...
<asp:GridView ID="GridView1" SkinID="CompacGrid" runat="server" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1" Width="400px" AllowPaging="True" BackColor="White"
BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3"
GridLines="Vertical">
<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<Columns>
<asp:CheckBoxField headertext="mm" />
Thank you,
Steve
For some reason, Microsoft omitted the 'Value' property from its specification for CheckBox in ASP.NET, despite it being a completely valid feature of HTML. My guess is that they wanted it to be as similar to the WinForms CheckBox as possible (which also lacks a 'Value' property).
If you want to give your <asp:CheckBox /> or <asp:CheckBoxField /> a 'Value' property you will either have to extend the control yourself and define a custom 'Value' property, or make use of the code-behind to populate the Attributes or InputAttributes collection of the control. See this article for more details.
cbMyCheckBoxField.Attributes.Add("Value", "foo");
or
cbMyCheckBoxField.InputAttributes.Add("Value", "foo");
The main difference between these two approaches is that the former will not include the Value in the generated HTML (only ViewState), while the latter will.
Try setting the DataField attribute based on a boolean condition on the datasource object. It appears you're binding to an ObjectDataSource. Perhaps there's a boolean condition on the class -- say it's IsHired.
Perhaps something like:
<asp:CheckBoxField headertext="mm" DataField="IsHired" />
There's a sample on the MSDN CheckBoxField article.
To add onto Nathan's answer: I would use the RowDataBound event for your GridView. Assuming you bound to a DataTable, with the interesting column being [0].
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//Check for a data row
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Find the checkbox control by ID and set it.
((CheckBox)e.Row.FindControl("CheckBoxId")).Checked = IsItemChecked(((DataRowView)e.Row.DataItem)[0]);
}
}
The IsItemChecked function can be passed the data from the DataItem to create custom logic that passes back a boolean. Once you have the control, you can also add attributes to it. This is a powerful technique once you master it.

Set DetailsView as selected row of GridView

I am creating a GridView/DetailsView page. I have a grid that displays a bunch of rows, when a row is selected it uses a DetailsView to allow for Insert/Update.
My question is what is the best way to link these? I do not want to reach out to the web service again, all the data i need is in the selected grid view row. I basically have 2 separate data sources that share the same "DataObjectTypeName", the first data source retrieves the data, and the other to do the CRUD.
What is the best way to transfer the Selected Grid View row to the Details View? Am I going to have to manualy handle the Insert/Update events and call the data source myself?
Is there no way to link these two so they use the same data source ?
<asp:GridView ID="gvDetails" runat="server" DataKeyNames="ID, Code"
DataSourceID="odsSearchData" >
<Columns>
<asp:BoundField DataField="RowA" HeaderText="A" SortExpression="RowA" />
<asp:BoundField DataField="RowB" HeaderText="B" SortExpression="RowB" />
<asp:BoundField DataField="RowC" HeaderText="C" SortExpression="RowC" />
....Code...
<asp:DetailsView ID="dvDetails" runat="server" DataKeyNames="ID, Code"
DataSourceID="odsCRUD" GridLines="None" DefaultMode="Edit" AutoGenerateRows="false"
Visible="false" Width="100%">
<Fields>
<asp:BoundField DataField="RowA" HeaderText="A" SortExpression="RowA" />
<asp:BoundField DataField="RowB" HeaderText="B" SortExpression="RowB" />
<asp:BoundField DataField="RowC" HeaderText="C" SortExpression="RowC" />
...
The standard way to do it would be to have the selected item of the griview be a control parameter to the objectdatasource you have wired up to the detailsview. I would probably not worry too much about the overhead of retreiving data that you already have unless you are catering to users with such slow connections that you want to avoid roundtrips to the webserver at all costs.
If you really want to avoid that thenyou could pull the data out of the gridview using javascript/jquery and then do your inserts/updates via ajax calls. It would require lots more coding though.
This is a really old thread, but in case anyone came here looking for an answer like I did, a simple solution is to add this function to your code:
(Note that this only works if the rows in your GridView match the entries in your DetailsView.)
protected void GridView1_OnSelectedIndexChanged(object sender, EventArgs e)
{
DetailsView1.SetPageIndex(GridView1.SelectedIndex);
}
And modify the GridView and DetailsView to include these settings:
<asp:GridView ... OnSelectedIndexChanged="GridView1_OnSelectedIndexChanged" ... >
<asp:DetailsView ... AllowPaging="True" ... >
This will make the selected page in the DetailsView match the selected index in the GridView.
You can hide the paging options in the DetailsView properties if you dont want users to navigate using paging in the DetailsView.

Categories

Resources