Selectively apply css to a row in a gridview - asp.net

I'm looking for a way to selectively apply a CSS class to individual rows in a GridView based upon a property of the data bound item.
e.g.:
GridView's data source is a generic list of SummaryItems and SummaryItem has a property ShouldHighlight. When ShouldHighlight == true the CSS for the associated row should be set to highlighted
any ideas?

very easy
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView drv = e.Row.DataItem as DataRowView;
if (drv["ShouldHighlight"].ToString().ToLower() == "true")
e.Row.CssClass = "highlighted";
}
}
the code above works if you use a DataTable as DataSource
change to:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
myClass drv = (myClass)e.Row.DataItem;
if (drv.ShouldHighlight)
e.Row.CssClass = "highlighted";
}
}
just for the example above when using generics:
public class myClass
{
public Boolean ShouldHighlight
{ get; set; }
}
if you are working with Generics (List, Dictionary, etc)
keep in mind:
e.Row.dataItem
always return the entire object that you are populating the row with, so it is easy from here to manipulate the appearance of the data in the webpage.
you should use RowDataBound event that will trigger after the data is attached to the row object but not yet written the HTML code in the page, in this way you can check the ShouldHighlight value (I converted to a String cause I do not know the type, you can change it if you know it's a boolean value).
this code runs much faster than megakemp code cause you're not creating a List object and populated with the entire data source for each row...
P.S. take a look at this website, you can find several tutorials for your project using the GridView object

One thing you want to keep in mind is that setting the Row.CssClass property in the RowCreated or RowDataBound event handlers will override any default styles you may have applied at the grid level. The GridView gives you easy access to row styles via properties such as:
gvGrid.AlternatingRowStyle.CssClass = ALTROW_CSSCLASS
gvGrid.RowStyle.CssClass = ROW_CSSCLASS
However, when you assign a CssClass value to a specific row, as is your need in this case, the assignment overrrules any top-level assignment at the grid level. The assignments will not "cascade" as we might like them to. So if you want to preserve the top-level class assignment and also layer on your own, more specific one, then you would need to check the rowState to see what kind of row you are dealing with and concatenate your class names accordingly
If(item.ShouldHighlight)
{
If(e.Row.RowState == DataControlRowState.Alternate)
{
e.Row.CssClass = String.Format("{0} {1}", "highlight", ALTROW_CSSCLASS)
}
else
{
e.Row.CssClass = String.Format("{0} {1}", "highlight", ROW_CSSCLASS)
}
}

Related

Telerik RadGrid GridDataItem - how to determine if column exists?

I'm using a base class to modify the behavior of any Telerik RadGrid that appears on my ASP.Net pages. In the base class, I want to perform certain operations (set Css, tool tips, etc) on many common columns, but not every common column exists in every grid.
In the ItemDataBound event I'm getting an instance to the GridDataItem and in turn I want to get a reference to one or more of the contained cells of the GridDataItem:
var cell = gridDataItem["ColumnUniqueName"]
Problem is that this throws a GridException if the named column doesn't exist:
Cannot find a cell bound to column name 'ColumnUniqueName'
Is there a way to test for existence of a column by name before referencing it or am I
stuck using try catch?
Will sent me on the right path:
var tableView = gridDataItem.OwnerTableView;
var gridColumn = tableView.Columns.FindByUniqueNameSafe(uniqueName);
if (gridColumn != null)
{
var cell = gridDataItem[gridColumn];
...
Try using the RenderColumns collection:
protected void rgGrid_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
bool found = (from d in rgGrid.MasterTableView.RenderColumns select d).Any(d => d.UniqueName == "ColumnUniqueName");
}
}

Displaying information from 1st object in a list in a GridView

I have a list of customers, each of which has a list of transactions. What I need to show is the list of customers and the details of their last transaction.
I've retrieved the details into a List of Customer, each with a List of Transaction as a property (called Transactions)
I'm trying to show the data of the transaction, and I thought that I could bind to a data field of Transactions[0].TransactionDate, but the GridView doesn't recognise that. Is there some other syntax, is it not possible, or what's a good workaround for this?
What you need to do is create a gridView rowDataBound event and in this event you can do something like this. The reason for this is as it will give you alot more control over the binding.
protected void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Customer> customer = (Customer)e.Row.DataItem;
Label lblTransaction = ((Label)e.Row.FindControl("LabelTransaction"));
lblTransaction.text = customer.Transactions[0].TransactionDate;
//do what ever you want to do here using the value of your label
}
}
You should be able to cast the dataitem, then read the value from that. e.g.
((YourClassName)Container.DataItem).Transactions[0].TransactionDate

Two way binding with custom expression?

I am using a gridview in my asp.net project to view and modify some records from the database. The database has two columns: start_date and end_date. When a new record is created these columns contains null, but they can be modified later using the gridview update command.
In gridview I have two template fields (having names start_date and end_date) in which I have placed two calendar controls. Upon clicking an update link of gridview it always returns an error because of the null value binding to the calendar. I have used this helper function to solve it:
protected DateTime ReplaceNull(Object param)
{
if (param.Equals(DBNull.Value))
{
return DateTime.Now;
}
else
{
return Convert.ToDateTime(param);
}
}
and used these two custom expressions in calendar control's SelectedDate:
ReplaceNull(Eval("start_date"))
ReplaceNull(Eval("end_date"))
The problem is that two-way data binding the calendars upon selecting a date does not update the database table. Are there any workarounds? Or alternatively, a better solution would be appreciated.
I don't know why you let them null when insert a new record , but many ways you can solve this problem i think .
one of them : in the RowDataBound event of the Gridview
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.Cells[1] == null) //the index of the start_date
{
e.Row.Cells[1].Text = DateTime.Now.ToString(); // in your case you will make the selected date of the calender(through casting to calender) with the value you need.
}
}
}
Or: you can catch the exception , you meet in your Update button through
try and catch block.

How can I retrieve a subset of data from entity object data source and pass to another page

I am playing about just now trying to teach myself a little bit about the entity framework.
I have a Gridview data bound to a Entity Date Source using the Entity Framework. If I select certain items in that list I then wish to redirect another page and populate another gridview with just the items selected (but with more detail, different includes/navigation properties)
This is probably the most simple thing but I have spent 2 hours banging my head on the wall trying to get this to work.
Essentially I have a continue button which when clicked should identify all the UIDs (a column in the gridview) of the rows and allow me to subset to just these rows and pass them to another page to be rebound to another datagrid
Any ideas???
Well, the big picture is that you should get those IDs, pass them to the other page, and then use a query with Contains; see this question for an idea of how to use it:
How search LINQ with many parametrs in one column?
Assuming you haven't used DataKeys in your GridView, this would be my approach.
Page 1
protected void Button1_Click(object sender, EventArgs e)
{
var checkedItems = new List<int>();
foreach (GridViewRow row in GridView1.Rows)
{
var checkbox = (CheckBox)row.FindControl("CheckBox1");
if (checkbox.Checked)
{
checkedItems.Add(int.Parse(row.Cells[1].Text));
}
}
Session["checkedItems"] = checkedItems;
Response.Redirect("Page2.aspx");
}
Page 2
protected void Page_Load(object sender, EventArgs e)
{
var checkedItems = (List<int>)Session["checkedItems"];
Session["checkedItems"] = null;
foreach (var checkedItem in checkedItems)
{
Response.Write(checkedItem);
}
}
Using the IDs in the checkedItems List you can now query those from you DB and finally assign the Result to your GridView on the second page.
Instead of using Session you could pass the IDs via QueryString.

Accessing Row Data In Telerik RadGrid (Server Side)

Ive no problems using Javascript to read the rows of a telerik radgrid component im using however I can seem to find anyway to access the row data server side when a postback occurs. Ive spent ages looking for solution but no luck.
Any pointers would be greatly appreciated.
Tony
You might want to look at the DataKeyValues property of the OwnerTableView object, which will let you access a collection of values that represent the fields in a given row. I use it during the EditCommand event handler, since a user of my site is directed to an edit page if they click on the link to edit a row in the grid, and I need to pass along certain info about the given row in the query string.
If this turns out to be what you need, you'll also need to define which fields should be made available through this property. To do that, look at the MasterTableView.DataKeyNames property in the property sheet for the grid. You basically specify a comma-delimited list of field names.
The server-side is the easy part:
GridItemCollection gridRows = TestGrid.Items;
foreach (GridDataItem data in gridRows)
{
ItemClass obj = (ItemClass)data.DataItem;
}
It's the client side part that I don't know! :[
private Int32 GetID()
{
foreach (Telerik.Web.UI.GridDataItem dataItem in radGrid.MasterTableView.Items)
{
if (dataItem.Selected == true)
{
Int32 ID = (Int32)dataItem.GetDataKeyValue("ID");
return ID;
}
}
throw new ArgumentNullException("Id Not found");
}
This is the one that works for me and uses the RadGrid.SelectedItems collection.
protected void LinkButton1_Click(object sender, EventArgs e)
{
List<Guid> OrderIdList = new List<Guid>();
foreach (GridDataItem OrderItem in this.RadGrid1.SelectedItems)
{
OrderIdList.Add(new Guid(OrderItem.GetDataKeyValue("OrderId").ToString()));
}
}
If you correctly created your controls in markup or page init for dynamic controls, then the RadGrid will properly restore state.
You can access the initial values that were loaded from the data source like this example below, provided you told the table view in question to keep the columns around in the data keys.
protected T GetInitialGridData<T>(GridDataItem item, string uniqueColumnName) {
item.ThrowIfNull("item");
uniqueColumnName.ThrowIfNullOrEmpty("uniqueColumnName");
return (T)item.OwnerTableView.DataKeyValues(gridItem.ItemIndex)(columnName);
}
If you are using a dynamic custom template column, and need to get to any values that may now be in their states, you can use:
protected string GetCustomTextBoxValue(GridDataItem item, string controlID) {
item.ThrowIfNull("item");
controlID.ThrowIfNullOrTrimmedEmpty("controlID");
return ((TextBox)item.FindControl(controlID)).Text;
}
private Int32 GetID()
{
foreach (Telerik.Web.UI.GridDataItem dataItem in radGrid.MasterTableView.Items)
{
if (dataItem.Selected == true)
{
// Int32 ID = (Int32)dataItem.GetDataKeyValue("ID");
Int32 ID =Convert.ToInt32(dataItem.GetDataKeyValue("ID"));
return ID;
}
}
}
//this will work

Resources