I have a grid view displaying the messages a user has. Each message the user has is being marked whether it has been read or unread as a bit in my database table.
Is there a way how I can change the style of certain rows in my grid view according to whether the messages are read or unread? I wish to display the whole row with an unread message in bold.
You will need to use the RowDataBound event for such a task. Here is an example:
<asp:GridView ID="GridView1" runat="server" OnRowDataBound="GridView1_RowDataBound" >
...
</asp:GridView>
.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
// searching through the rows
if (e.Row.RowType == DataControlRowType.DataRow)
{
bool isnew = (bool)DataBinder.Eval(e.Row.DataItem, "IsNew");
if ( isnew ) e.Row.BackColor = Color.FromName("#FAF7DA"); // is a "new" row
}
}
Reference: http://blog.devexperience.net/en/5/Change_background_color_of_GridView's_Rows.aspx
Related
I'm trying to take a GridView and get back the data from the row that was clicked. I've tried the code below and when I click the row I get back the selected index but when I look at the actual rows in the GridView they show empty. Not sure what I am missing.
.ASP make my grid.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True"
CssClass="datatables" Width="100%"
DataSourceID="SqlDataSource1"
GridLines="None" ShowFooter="True" AllowSorting="True"
onrowcreated="GridView1_RowCreated"
onrowdatabound="GridView1_RowDataBound" ShowHeaderWhenEmpty="True"
onrowcommand="GridView1_RowCommand"
onselectedindexchanged="GridView1_SelectedIndexChanged">
<HeaderStyle CssClass="hdrow" />
<RowStyle CssClass="datarow" />
<PagerStyle CssClass="cssPager" />
</asp:GridView>
On each row data bound I make sure that the click should set the selected index.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(GridView1, "Select$" + e.Row.RowIndex);
}
}
Then when the selected index changes by clicking this gets fired which I can put a breakpoint on the first line and I see the index of what I clicked on get stored in a. However when I get to the foreach it skips right past it because it shows GridView1 having a Count of 0 rows. In theory it should have a couple hundred rows and when the index matches it should grab the data in the 6th cell over and store it in string b. Why am I getting no rows on the click?
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
int a = GridView1.SelectedIndex
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowIndex == a)
{
b = row.Cells[6].Text;
}
}
}
Here is my page load.
protected void Page_Load(object sender, EventArgs e)
{
c = HttpContext.Current.Session["c"].ToString();
SqlDataSource1.ConnectionString = //My secret
string strSelect = "SELECT columnnames from tablenames where c in (#c)
SqlDataSource1.SelectParameters.Clear();
SqlDataSource1.SelectCommand = strSelect;
SqlDataSource1.SelectParameters.Add("c", c);
try
{
GridView1.DataBind();
}
catch (Exception e)
{
}
GridView1.AutoGenerateColumns = true;
}
Try just grabbing the row from the SelectedRow property:
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow row = GridView1.SelectedRow;
string b = row.Cells[6].Text;
}
It's my understanding that the Rows collection doesn't get repopulated on PostBacks when you're using those data source controls (like SqlDataSource).
You could probably use your existing code if you called .DataBind() on your GridView prior to trying to iterate through the Rows:
GridView1.DataSourceID="SqlDataSource1";
GridView1.DataBind();
But that seems a little hacky.
After seeing your Page_Load, I see that you need to wrap your databinding code in an if(!Page.IsPostBack) block. Databinding on every postback is interrupting the process of ASP.NET maintaining the state of your controls via the ViewState.
I hide my columns using the solution in following link
How to hide a TemplateField column in a GridView
However this causes problems with update operations, as gridview acts as hidden rows has null value. So how to hide columns after databind?
protected void begv_OrderDetail_RowCreated(object sender, GridViewRowEventArgs e)
{
((DataControlField)begv_OrderDetail.Columns.Cast<DataControlField>().Where(fld => fld.HeaderText == "FileNo").SingleOrDefault()).Visible = "False";
}
Try this,
grid1.Columns[columnIndex].Visible= false;
Edit based on comment of questioner, for getting values of hidden columns
You can use hidden fields to store column wise values. This article has example that will help how to use hidden fields.
Instead of hiding column you can put the data of columns in datakeynames and later access those values. This will be useful in grabbing how to use DataKeyNames. By this method you may need to pass the id from data key names and get the record.
try this example, (i don't speak english)
into RowDataBound ...
protected void gvTeste_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
teste listaTeste = e.Row.DataItem as ListaTeste;
if (listaTeste.ID == 0)
{
e.Row.Cells[2].Text = "Não Atribuido";
}
if (e.Row.Cells[7].Text == "01/01/0001" || e.Row.Cells[8].Text == "01/01/0001")
{
**e.Row.Visible = false;** // disable row
}
}
}
I have GridView with 2 columns.
The first column is: test-label (TemplateField)
The second: checkbox (asp:CheckBoxField) that connect to sql table with bit column (done).
I want that on page load - the page will check every row, where the checkbox = true, the test-label.visble will be false.
I know how to write code with SELECT statement to check the value from the SQL table, but don't know how to check every row on the gridview on the page-load.
how can I do that?
(i can't use findcontroll for the checkbox because it's checkboxfield and not just "checkbox".
<asp:CheckBoxField DataField="done" SortExpression="done" HeaderText="done?" />
so, what can I do here? maybe to replace that field with regular cb? (i don't know how to do there databind - on the regular cb).
you can use GridView.RowDataBound Event
so you can do something like
protected void GVRowDataBound(object sender, GridViewRowEventArgs e)
{
var check = (CheckBox) e.Row.FindControl("ID"); // ID is id of the checkbox
var lable = (Label) e.Row.FindControl("LableID");
if(check != null && lable != null)
{
if(check.Checked)
{
lable.Visible = false;
}
}
}
You can't do it in Page.Load because the GridView isn't databound yet.
Try handling GridView.RowDataBound.
Code:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox cb = (CheckBox)e.Row.FindControl("checkbox");
Label lbl = (Label)e.Row.FindControl("test-label");
lbl.Visible = !(cb.Checked);
}
}
I have a gridview, grid has 5 different columns ID,FirstName,LastName,DateOfBirth and Age, gridview can be edited, so I want to update the Age depending on DateOfBirth column so I have written the necessary functionality in OnRowBound function.When i execute the grid view page I get "String is not Recognized as valid datetime".
Here is the Function of OnRowBound
protected void UserInfoGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DateTime DOBOnGrid = DateTime.ParseExact(e.Row.Cells[3].Text,"MM/dd/yyyy",null);
Label tAge = (Label)e.Row.Cells[4].FindControl("txtAge");
TimeSpan ts = DateTime.Now - DOBOnGrid;
int CurrAge = ts.Days / 365;
tAge.Text = CurrAge.ToString();
}
}
<asp:GridView ID="UserInfoGrid" runat="server" AutoGenerateColumns="False" CellPadding="3"
DataKeyNames="userid" DataSourceID="DataSrcUserInfo"
AllowPaging="True" OnRowDataBound="UserInfoGrid_RowDataBound"
OnRowUpdated="Update" OnRowDeleted="Delete" PageSize="10" >
can anyone help me with this
Thanks,
First of all, shouldn't the code your are showing be in the RowUpdating event handler? As for the error you are getting, its obviously due to a bad formatted string in the Birthday cell.
Have you checked for empty strings? I'm guessing you are getting the exception even before the GridView renders on screen as its in the RowDataBound event handler which fires when the GridView is loading.
I have nested a repeater control in Gridview. Right now it is showing gridview rows and repeater header for every case(whether data is there or not for that particular grid view row in the repeater control). I want to hide the gridview row and repeater control header when there is no data present for that particular gridview row.
Thanks,
That case I handled at code level by filtering the resulted data table.
Now the another problem I am facing:
I have allowed the paging on the gridview i.e. pagesize 3.
When page loads it works fine, but when I go to page 2 then it generates following error:
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
Below is the code to fill the grid, paging and fill repeater on rowdatabound event of grid.
private void FillGrid()
{
clsCustomFunctions objShort = new clsCustomFunctions();
grd1.DataSource = objShort.GetAll();
}
protected void grd1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
try
{
FillGrid();
grd1.PageIndex = e.NewPageIndex;
grd1.DataBind();
}
catch (Exception ex)
{
lblMsg.Text = ex.Message;
}
}
protected void grd1_RowDataBound(object sender, GridViewRowEventArgs e)
{
clsCustomFunctions objShort = new clsCustomFunctions();
if (e.Row.RowType == DataControlRowType.DataRow)
{
((HtmlTable)e.Row.FindControl("gridTable")).BgColor = "#006699";
Repeater rpt = (Repeater)e.Row.FindControl("rpt1");
rpt.DataSource = objShort.GetResult(Convert.ToInt32(grd1.DataKeys[e.Row.DataItemIndex].Value));
rpt.DataBind();
}
}
grd1.DataKeys[e.Row.DataItemIndex].Value line is throwing error. How to handle this to pass values of page 2 only.
Try handling the OnRowDataBound event of the grid. This gives you a GridViewRowEventArgs object (say e).
You can then look at e.Row.DataItem to get the data it is binding to to check if you need to hide the header.
You can use e.Row.FindControl("RepeaterName") to get the repeater to manipulate as you want.