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 want specific row dropdown to be shown when the same row's checkbox is selected. But having problem as all the dropdowns of the grid are shown on one row's checkbox selection.
This is the Grid:
<asp:TemplateField HeaderText="Advertise Id" HeaderStyle-Width="150px" HeaderStyle-Font-Size="14px" HeaderStyle-ForeColor="Black">
<ItemTemplate>
<div style="text-align: left;">
<asp:TextBox runat="server" Width="120px" ReadOnly="true" ID="TextBoxAdvertiseId" Text='<%# Eval("AdvertiseIdName")%>' />
<input type="checkbox" class="CheckBoxImage" onclick="CheckBoxImage()" />
<asp:DropDownList CssClass="DDAdvertise" runat="server" Width="130px" ID="drpdwnadvertiseAdd"></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
This is the jquery Code:
function CheckBoxImage() {
var flag = false;
$('.GridLocation input[type="checkbox"]').each(function () {
var checkbox = $('.GridLocation input[type="checkbox"]');
var row = $(this).parent().parent().parent().parent().parent();
if ($(this).is(':checked')) {
flag = true;
$(row).find('.DDAdvertise').show(); // Problem is in .DDAdvertise as it is a classname so it's selecting all the dropdowns
} else {
$(row).find('.DDAdvertise').hide();
}
if (flag) {
$(row).find('.DDAdvertise').show();
}
else {
$(row).find('.DDAdvertise').hide();
}
});
}
Now, the problem is i am using class name (.DDAdvertise) in jquery which is showing all the dropdowns. I want the specific dropdown to be shown whose row's checkbox is selected.
I am trying to validate a drop down inside a gridview on a button click. If the drop down has no selection then i want to fire the javascript but the code is not firing at all. I am not sure what am i doing wrong here so please help. thanks.
Here is the button code in the aspx file:
<asp:Button ID="btnSubmit" runat="server" Text="Submit" Width="183px" Visible="true"
onclick="btnSubmit_Click"
OnClientClick="return validate();"
Font-Bold="True" Font-Size="Medium" Height="30px"
style="margin-right: 1px; margin-left: 185px;" ForeColor="#336699" />
here is the javascript in the head section of my page:
<script type="text/javascript">
function validate() {
var flag = true;
var dropdowns = new Array(); //Create array to hold all the dropdown lists.
var gridview = document.getElementById('<%=GridView1.ClientID%>'); //GridView1 is the id of ur gridview.
dropdowns = gridview.getElementsByTagName('--'); //Get all dropdown lists contained in GridView1.
for (var i = 0; i < dropdowns.length; i++) {
if (dropdowns.item(i).value == '--') //If dropdown has no selected value
{
flag = false;
break; //break the loop as there is no need to check further.
}
}
if (!flag) {
alert('Please select value in each dropdown');
}
return flag;
}
</script>
here is my drop-down in the aspx:
<ItemTemplate>
<asp:Label ID="lblAns" runat="server" Text='<%# Eval("DDL_ANS")%>' Visible="false"></asp:Label>
<asp:DropDownList ID="ddl_Answer" runat="server" AutoPostBack="false">
</asp:DropDownList>
</ItemTemplate>
here is the code behind for the dropdown
ddl_Answer.DataSource = cmd1.ExecuteReader();
ddl_Answer.DataTextField = "DD_ANSWER";
ddl_Answer.DataValueField = "DD_ANSWER";
ddl_Answer.DataBind();
ddl_Answer.Items.Insert(0, new ListItem("--"));
How are you trying to select the dropdown using javascript. You probably want this
dropdowns = gridview.getElementsByTagName('select');
First of all what I want to do is to pre select a value in my RadComboBox ,and if this value is not selected something else is selected then change the visibility to of some specific fields hidden.
My problem is that I'm able to make my pre select but somehow I can not change the status of my visibility for my specific fields when this pre selected value has changed.
What I have tired is to do it with a standard event OnSelectedIndexChanged but some how this is not triggering why so ever.. I have also added AutoPostBack=true as well as ViewStateMode=Enabled"
First my field's
Here comes my preslect as well here I would like to trigger the visibility change
<div class="formRowDiv">
<asp:Label ID="Activitylbl" runat="server" Text="Activity" CssClass="formLabel" />
<telerik:RadComboBox ID="rcbActivity" CssClass="rowForm" ViewStateMode="Enabled" runat="server" Width="260px" EmptyMessage="- Activity -"
DataTextField="ActivityId" DataValueField="ActivityId" AutoPostBack="true" OnSelectedIndexChanged="rcbActivity_SelectedIndexChanged">
</telerik:RadComboBox>
<asp:RequiredFieldValidator runat="server" Display="Dynamic" ControlToValidate="rcbActivity"
ErrorMessage="Can not be empty" CssClass="rowFormValidation" />
</div>
What I want to hide:
<div class="formRowDiv">
<asp:Label ID="ActivityDescription" runat="server" Text="ActivityDescription" CssClass="formLabel" Visible="false"/>
<telerik:RadTextBox runat="server" ID="rtbActivityDescription" Wrap="true" Height="50" TextMode="MultiLine" AutoPostBack="true" CssClass="rowForm" ReadOnly="true" Visible="false" />
</div>
How I do my pre selection :
In my databind method that is called in my Page_Load
I firrst loop and then do a pre select
foreach (Activity item in ctx.Activity.OrderBy(l =>l.Code))
{
rcbActivity.Items.Add(new RadComboBoxItem(item.FullActivity, item.ActivityId.ToString()));
if (rcbActivity.Items.FindItemByValue("4") != null)
{
rcbActivity.SelectedIndex = rcbActivity.Items.IndexOf(rcbActivity.Items.FindItemByValue("4"));
ActivityDescription.Visible = true;
rtbActivityDescription.Visible = true;
rtbActivityDescription.ReadOnly = false;
}
}
Here is how I would hide my Fields
protected void rcbActivity_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
ActivityDescription.Visible = true;
rtbActivityDescription.Visible = true;
rtbActivityDescription.ReadOnly = false;
}
In case your controls are in an update panel then try removing it if the update panel is not so important and see if the changes u make to the controls in the server side are getting affected properly
I've an asp repeater which has some fields inside an ItemTemplate. Each item in the repeater has an "add to cart" asp:ImageButton and an invisible asp:Label as well. The code looks like this:
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="addToCart">
<HeaderTemplate>
<table id="displayTable">
</HeaderTemplate>
<ItemTemplate>
<td>
<!-- fields like name, description etc in the repeater are present; i've omitted to show them here-->
<asp:Label ID="addedToCartLabel" runat="server" Visible="false"></asp:Label>
<asp:ImageButton ID="addToCartImg" runat="server" ImageUrl="hi.jpg" Width="75px" Height="50px" />
</td>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
When a particular ImageButton in the repeater is clicked, I'm trying to display "added to cart" as the text of its corresponding Label, and make the clicked ImageButton Visible=false. I've tried using the OnItemCommand function for the ASP:Repeater. The method is "addToCart":
<>
void addToCart(Object Sender, RepeaterCommandEventArgs e)
{
Cart cart = new Cart();
cart.instrument_id = //id of product from repeater based on user click
String userName = Membership.GetUser().ToString();
cart.user_name = userName;
cart.quantity = 1;
var thisLbl = (Label)e.Item.FindControl("addedToCartLabel");
var thisImg = (ImageButton)e.Item.FindControl("addToCartImg");
try
{
database.Carts.InsertOnSubmit(cart);
database.SubmitChanges();
thisImg.Visible = false;
thisLbl.Text = "Added to Cart!";
thisLbl.Visible = true;
}
catch (Exception ex)
{
thisImg.Visible = false;
thisLbl.Text = "Processing failed;please try again later";
thisLbl.Visible = true; ;
}
}
The aspx page is populated properly. However, when I click on any of the ImageButtons in the repeater, I get the following error:
Server Error in '/mysite' Application.
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%# Page EnableEventValidation="true" %> in a page.
For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.
If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback
or callback data for validation.
Can someone help me with this?
May I suggest doing this with client-side javascript rather than a server-side call?
<asp:Label ID="addedToCartLabel" runat="server" Visible="false"></asp:Label>
<asp:ImageButton ID="addToCartImg" runat="server" ImageUrl="hi.jpg" Width="75px" Height="50px" />
becomes
<asp:Label ID="addedToCartLabel" runat="server" Visible="false"></asp:Label>
<asp:ImageButton ID="addToCartImg" runat="server" onclick="javascript:function() { this.this.style.display='none'; document.getElementById(this.parentNode.firstChild.id).style.display='block'; }" ImageUrl="hi.jpg" Width="75px" Height="50px" />