After reading Formatting the DataList and Repeater Based Upon Data (C#) on Microsoft Website I found the following code sample.
protected void ItemDataBoundFormattingExample_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Programmatically reference the ProductsRow instance bound
// to this DataListItem
Northwind.ProductsRow product =
(Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
// See if the UnitPrice is not NULL and less than $20.00
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
{
// TODO: Highlight the product's name and price
}
}
}
However in the above I would like to know where Northwind.ProductsRow product is coming from. Is it from the Northwind database name or somewhere else.
this is a great question, and like some time travel movie, I REALLY WISH someone had and did explain how this works. You note that sometimes the "data source" of the datalist works, and sometimes it does not, and why is this so???
So, the data source comes from WHEN the control was "binded" or spoon fed the data source.
So, on page load, there is most likly some code that set-up and "binds" the data control. Or, it might be that a sqldatasource was dropped into the web page, but AGAIN, either way?
The page load will then trigger the row data bound event.
(ItemDataBound).
So, first BIG tip:
The e.Item.DataItem used IS ONLY available DURING the data bind process. That quite much means at data bind time and the ItemDataBound event.
So, WHEN you shove a data source INTO the GridView, Datalist, ListView, repeater etc controls? And use the data bound event (the name varies a wee bit, bu they all do the same thing), then the DataItemView is ONLY available DURING the row data bind process and hence you are 100% free to use that data source DURING the data bind event - BUT NOT AFTER!!!!!
After, binding has occured, you find that the the dataitem (and control datasoruce is NOW null!!!!). This is VERY different then desktop versions of such controls in .net (in desktop land, you actually can get/use/see the ACTUAL object used for each row!!! - and they persist!!!!
In web land, that data source is converted to a DataRowView.
However, what is the basic knowledge here?
Well, it means that your data control does NOT have to display or hide all of the columns from the database, but you ARE STILL FREE to use those additional columns for things like tax calculations, or for formatting controls based on OTHER columns that you have in the datasource BUT ARE NOT DISPLAYED!!!
And you see BOATLOADS of examples posted where people use hidden fields and all kinds of tricks, and they did that because they DID NOT KNOW the above!!!
Now, it not clear if you want to use a "datalist" control. They tend to be good for say one reocrd, or say several records in a "card like" view - not a table like layout.
So, for a table like layout, I suggest using ListView (most flexible), or for simple, and not too fancy, then use GridView.
But, DataList, listView, GridView, Repeater ? They all of this Row bound (or Item bound) event (they all are VERY close named).
And as noted, JUST like your question, in most cases this event can be used for addtional formatting.
Lets do this with a GridView - (since it easy).
So, say we have a grid of hotel names, but I want to highlight in say blue color ONLY hotels that are active. But I ALSO do NOT want to display the "active" column from the data base in that grid.
So, say this simple markup:
<style> .MyCenter {text-align:center;}</style>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" cssclass="table" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" ItemStyle-Width="120px" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="View" >
<HeaderStyle CssClass="MyCenter"/>
<ItemStyle CssClass="MyCenter" />
<ItemTemplate>
<asp:Button ID="bView" runat="server" Text="View" CssClass="btn" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now, our code to load, we have this:
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 now have this:
So, lets use the ItemDataBound event (RowdataBound for Gridview) to highlight the Hotel name and descrption ONLY for Hotels that are active. As noted, we do NOT display "Active" column in the gridview, but with Row data bound event, we still have use of the FULL row.
So, we can add this code to the Row data bound event.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get the full data row used for binding
DataRowView OneRow = e.Row.DataItem as DataRowView;
// lets highlist the hotel name + description
if ((bool)OneRow["Active"])
{
e.Row.Cells[3].BackColor = System.Drawing.Color.LightSteelBlue;
e.Row.Cells[4].BackColor = System.Drawing.Color.LightSteelBlue;
}
// that button is not centered "vertical", so lets do that
Button btn = e.Row.FindControl("bView") as Button;
DataControlFieldCell g = btn.Parent as DataControlFieldCell;
g.Style.Add("vertical-align", "middle");
}
}
And now we we get this:
So, what about the view item click? For that we could use a datalist as you have, and we could then hide the grid, display the datalist, and we would be quite much on our way with a grid to edit items, then right?
Coffee break - I'll be back in a bit to add the view + datalist to see/view/edit one item.
Ok, part 2 - using a datalist to display above click
Ok, so lets drop in a data list - with a div area (to hide and show).
So, ok, now our data list we drop in.
<div id="MyEditArea" runat="server" style="width:44%;margin-left:35px;padding:8px;border:solid;display:none">
<asp:Datalist ID="DataList1" runat="server" DataKeyField="ID" >
<ItemTemplate>
<style>
.iForm label {display:inline-block;width:95px}
.iForm input {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm textarea {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm input[type=checkbox] {margin-right:6px}
</style>
<div style="float:left" class="iForm">
<label>HotelName</label>
<asp:TextBox ID="txtHotel" runat="server" Text='<%# Eval("HotelName") %>' width="280" /> <br />
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" Text='<%# Eval("FirstName") %>' Width="140" /> <br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" Text='<%# Eval("LastName") %>' Width="140" /> <br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" Text='<%# Eval("City") %>' Width="140" /> <br />
<label>Province</label><asp:TextBox ID="tProvince" runat="server" Text='<%# Eval("Province") %>'
f="Province" Width="75"></asp:TextBox> <br />
</div>
<div style="float:left;margin-left:20px;width:420px " class="iForm">
<label>Description</label> <br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" Text='<%# Eval("Description") %>' ></asp:TextBox> <br />
<asp:CheckBox ID="chkActive" Checked='<%# Eval("Active") %>' Text=" Active" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkBalcony" Checked='<%# Eval("Balcony") %>' Text=" Has Balcony" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkSmoking" Checked='<%# Eval("Smoking") %>' Text=" Smoking Area" runat="server" TextAlign="Right" />
</div>
<div style="clear:both"></div>
<div style="float:left" class="iForm">
<asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel" CssClass="btn" style="margin-left:10px" />
</ItemTemplate>
</asp:Datalist>
And now our button click for the grid view - to display that one data list control + data.
Hum, started writing some code routine, so lets clean this up a bit.
Ok, so we now have this to load + format the gridview.
void LoadGrid()
{
GridView1.DataSource = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName");
GridView1.DataBind();
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get the full data row used for binding
DataRowView OneRow = e.Row.DataItem as DataRowView;
// lets highlist the hotel name + description
if ((bool)OneRow["Active"])
{
e.Row.Cells[3].BackColor = System.Drawing.Color.LightSteelBlue;
e.Row.Cells[4].BackColor = System.Drawing.Color.LightSteelBlue;
}
// button is not centered "vertical", so lets do that
Button btn = e.Row.FindControl("bView") as Button;
DataControlFieldCell g = btn.Parent as DataControlFieldCell;
g.Style.Add("vertical-align", "middle");
}
}
void CenterControl(Control c)
{
DataControlFieldCell g = c.Parent as DataControlFieldCell;
g.Style.Add("vertical-align", "middle");
}
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
And for the button click on the grid, we have this now:
protected void bView_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
int? PKID = GridView1.DataKeys[gRow.RowIndex]["ID"] as int?;
// Now load our datalist
string strSQL = "SELECT * from tblHotelsA WHERE ID = " + PKID;
DataList1.DataSource = MyRst(strSQL);
DataList1.DataBind();
// hide grid, show edit area
GridView1.Style.Add("display", "none");
MyEditArea.Style.Add("display", "normal");
}
So, now when we click on a row, we hide grid, show our data list control, and we now see/have this:
And just like the grid view, lets highlight the hotelname and description as light grey. Once again, we now use the data list row data bound event.
Say, this:
Note how we don't use .cells for the data list, but have to use find control.
protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
{
if ( (e.Item.ItemType == ListItemType.Item) |
e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRowView gData = e.Item.DataItem as DataRowView;
if ((bool)gData["Active"])
{
TextBox txtHotel = e.Item.FindControl("txtHotel") as TextBox;
txtHotel.BackColor = System.Drawing.Color.LightSteelBlue;
TextBox txtDescript = e.Item.FindControl("txtNotes") as TextBox;
txtDescript.BackColor = System.Drawing.Color.LightSteelBlue;
}
}
}
And, you do have to check for item, and "alternating" item.
But, now, when we click on a grid row, we get this:
I have a simple checkBox in Editable gridView :
<asp:TemplateField HeaderText="Editable">
<ItemTemplate>
<asp:Label runat="server" Text="<%# Item.IsEditable %>" />
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox ID="CheckBoxEditable " runat="server" Text="Editable"></asp:CheckBox>
</EditItemTemplate>
</asp:TemplateField>
When I click on edit button in the row, I would like that checkBox is already checked if value is true. (IsEditable is a boolean)
Text Field is easy because I have a BindItem on Text property in EditItemTemplate. But it's not the same for checkBox or dropdownlist
GridView
I use a UpdateItem Method to update my data in database. I tried a small condition to check my checkBox but it does'nt work.
public void GridViewRisquesAggravants_UpdateItem(IndexViewModel item)
{
try
{
if (ModelState.IsValid)
{
CheckBox chbEdit = (CheckBox)GridView.Rows[this.GridView.EditIndex].FindControl("CheckBoxEditable")
if (item.IsEditable)
chbEdit.Checked = true;
new TypeService().Update(new Type
{
IsEditable = item.IsEditable,
});
this.GridView.DataBind();
}
}
catch
{
throw;
}
}
It makes sense because I am not in the right function to declare this. But I just have 3 methods in my webform.
SelectMethod="GridView_GetData"
UpdateMethod="GridView_UpdateItem"
DeleteMethod="GridView_DeleteItem"
Where can I do this?
(And I have the same problem with datas on dropdownList. I don't know where I recover current value during editing)
Thanks in advance
(Sorry I am beginner about webforms and my english is not perfect)
Evy
use the following code instead for checkbox declaration in edit template
<asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# Convert.ToBoolean("true") %>' />
CheckBox chbx = GridView1.HeaderRow.FindControl("CheckBoxEditable") as CheckBox;
if (chbx != null && chbx.Checked)
{
//code here
}
else
{
//else condtion
}
hope this helps
Where can I do this?
Try it in RowDataBound event:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox chbEdit = (CheckBox)e.Row.FindControl("CheckBoxEditable");
string value = ((Label)e.Row.FindControl("lblID")).Text;
if (value=="True")
chbEdit.Checked = true;
else
chbEdit.Checked = false;
}
}
Note: Don't forget to add OnRowDataBound in GrindView <asp:GridView ID="GridView1" runat="server" OnRowDataBound="GridView1_RowDataBound" >
I added the property Checked=<%# BindItem.IsEditable %> on CheckBox Control and it works perfectly.
So I have a GridView for a C# web application, that has a Buttonfield, and when that button is clicked, I need to get the value of one of the fields for that row and store it in a variable for processing in some way.
However, neither the GridView nor the ButtonField seem to possess any means of doing this.
Can anyone recommend a way of getting data from a GridView, or if this is not possible, a different type of view that does offer this functionality, while still displaying a whole table (eg, not a DetailsView)
You can Check this link: https://msdn.microsoft.com/en-us/library/bb907626(v=vs.140).aspx.
Define the CommandName of the Button.
In the GridView Define the RowCommand Event and Check the CommandName.
Get the Index of the Row.
Get the Column with GridView.Rows[index](columnIndex)
If you are using asp:TemplateField like shown below then you can access the row content using RowCommand
Markup
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblCode" runat="server" Text='<%# Eval("CustomerID") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:ButtonField CommandName="AddCode" Text="Add New"/>
Code
protected void gvwSearch_RowCommand(object sender, GridViewCommandEventArgs e)
{
if(e.CommandName == "AddCode")
{
var clickedButton = e.CommandSource as Button;
var clickedRow = clickedButton.NamingContainer as GridViewRow;
var rows_lblCode = clickedRow.FindControl("lblCode") as Label;
// now you can acccess all the label properties. For example,
var temp = rows_lblCode.Text;
}
}
I have a gridview with a hyperlink in first column. Upon clicking the hyperlink, the user is redirected to Vendor.aspx. Now, I need to pass the consumer id (of the clicked row) as a query string to the Vendor.aspx.
What is the best method to achieve it? Is there a way in which we can handle it using markup code only?
<asp:GridView ID="grdConsumers" runat="server" AutoGenerateColumns="False"
EnableViewState="True" >
<Columns>
<asp:TemplateField HeaderText="ConsumerID" SortExpression="ConsumerID" >
<ItemTemplate>
<asp:HyperLink ID="lnkConsumerID" href="Vendor.aspx" runat="server"><%# Eval("ConsumerID")%></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Status" DataField="Status" SortExpression="Status"></asp:BoundField>
</Columns>
</asp:GridView>
READINGS:
Set Gridview DataNavigateUrlFormatString Dynamically inside User Control(ASCX)
How do I add "&Source" to DataNavigateUrlFormatString?
Select row in GridView with JavaScript
How to bind the URL of a GridView HyperLinkField when the bound value contains a colon?
asp.net gridview DataNavigateUrlFormatString from DataSource
Try using the DataNavigateUrlFormatString
<ItemTemplate>
<asp:HyperLinkField DataNavigateUrlFields="ConsumerID" DataTextField="ConsumerID" DataNavigateUrlFormatString="Vendor.aspx?id={0}" />
</ItemTemplate>
... it will spare you Eval() and the problem with single/double quotes when putting it inside your href.
You can substitute the DataTextField if you like - I just put the ConsumerID there to be consistent with your example.
Rewrite your hyperlink in gridview in .aspx file like this:
<asp:HyperLink ID="lnkConsumerID" runat="server" Text='<%# Eval("ConsumerID")%>' />
Then in code-behind create a RowDataBound event handler:
protected void grdConsumers_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType != DataControlRowType.DataRow) return;
var hlnkhlnk = (HyperLink)e.Row.FindControl("lnkConsumerID");
if (hlnkhlnk != null)
{
hlnkhlnk.NavigateUrl = "Vendor.aspx" + "?Consumer ID=" + hlnkhlnk.Text;
}
}
Hope it helps.
You can do same using at Grid view Item Data Bound Event
protected void grdConsumers_ItemDataBound(object sender,DataGridItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// Get your consumerId here
((HyperLink)e.Item.FindControl("Edit")).NavigateUrl = "Vendor.aspx?id=" + consumerId
}
}
I want to add a dropdownlist to every entry in a gridview.
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False"
onselectedindexchanged="GridView1_SelectedIndexChanged">
<Columns>
<asp:TemplateField HeaderText="Bank">
<ItemTemplate>
<asp:DropDownList ID="DropDown"
AutoPostBack="true" runat="server" DataTextField="Name" DataValueField="Name"
>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
At the back end i have the following code in order to bind a datatable to that dropdown list.
DataTable reader = BusinessLayer.BusinessLayerHandler.GetBankList();
DropDown.DataSource = reader;
DropDown.DataTextField = "NAME";
DropDown.DataValueField = "NAME";
DropDown.DataBind();
My problem is that the drop down list created at the grid view (DropDown) is not found at the back end as if it doesn't exist..
What can I do?
The DropDownList will be created for every single item in the GridView, so there can't be one field for the dropdownlists. Nevertheless, you can retrieve the DropDownList for a single row (e.g. in RowDataBound or RowCreated event)
protected void grid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(r.Row.RowType == DataControlRowType.DataRow)
{
DropDownList dropdown = e.Row.FindControl("DropDown") as DropDownList;
if(dropdown != null)
{ /* your code */ }
}
}
Or you can use an event of the DropDownList itself and access the sender parameter.
<asp:DropDownList ID="DropDown" OnLoad="dropdownLoad" />
protected void dropdownLoad(object sender, EventArgs e)
{
DropDownList dropdown = sender as DropDownList;
if(dropdown != null)
{ /* your code */ }
}
you can find dropdown into grid databound event by grid.findcontrol.