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.
Related
I am still a novice with asp.net, so I'm sure there are better ways to do some of this...
I want to allow a user to enter a date, and then execute an SQL query against a database to return all records matching that date. I want to display those records, and allow the user to select one for additional processing. It seemed like the DataGrid with a column of Pushbuttons was a good choice. In fact, I've done this before, but it those cases there was no user interaction involved. The page just ran a fixed SQL query. With what I'm doing now, the data is displayed as I want, but the Pushbuttons aren't working...the ItemCommand event doesn't fire.
I've read a lot of threads about the ItemCommand event not firing, but I still can't get this to work. My understanding is that I need to bind the DataGrid while not in a Postback, and I think my code does that. When I debug the Page_Load event, I can see that the code inside if (!IsPostBack){} is running, and the session variables have the expected data.
On the page that hosts the DataGrid, I have a 'Find' button that executes a SQL query against a database. The query uses a date entered into the textbox that is on that page. In the 'Find' button click event, I store the results of the query (a DataTable) in a session variable, then do a Redirect to re-load the page.
Once the page reloads, the session variables contain my expected data and the data is displayed in the DataGrid, along with the Pushbuttons. When I click any of the buttons in the DataGrid, the contents of the DataGrid disappear and the ItemCommand event does not fire.
Here's the definition of the DataGrid (updated to include the button):
<asp:Panel runat="server" ID="pnlSelect" HorizontalAlign="Left" Visible="true" style="margin-top:10px" >
Please select a participant.
<asp:DataGrid runat="server" ID="grdItems" AutoGenerateColumns="true" BorderColor="black" BorderWidth="1" CellPadding="3" style="margin-left:2px; margin-top:6px" OnItemCommand="grdSelect_ItemCommand" >
<Columns>
<asp:ButtonColumn HeaderStyle-HorizontalAlign="Center" ButtonType="PushButton" Text="Select" HeaderText="Select" CommandName="Select" >
<ItemStyle Width="60px" HorizontalAlign="Center"/>
</asp:ButtonColumn>
</Columns>
</asp:DataGrid>
</asp:Panel>
Here's the Page Load code (unneeded code-behind stuff is commented out):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Session["y"] != null)
{
txtFind.Text = Session["x"].ToString();
DataTable table = Session["y"] as DataTable;
Session.Remove("x");
Session.Remove("y");
if (table != null)
{
/*
ButtonColumn buttonColumn = new ButtonColumn
{
HeaderText = "Select",
Text = "Select",
CommandName = "Select",
ButtonType = ButtonColumnType.PushButton,
};
grdItems.Columns.Add(buttonColumn);
foreach (DataColumn c in table.Columns)
{
BoundColumn column = new BoundColumn
{
HeaderText = c.Caption,
DataField = c.Caption,
ReadOnly = true
};
grdItems.Columns.Add(column);
}
*/
grdItems.DataSource = table;
grdItems.DataBind();
}
}
}
}
Here's the relevant 'Find' button event code. I can't post the details of the sql query text, but that part does work and the DataTable does contain the expected data:
DataTable table = DatabaseHelper.FindBySQL(sqlText);
if (table != null && table.Rows.Count > 0)
{
Session["x"] = searchtext;
Session["y"] = table;
Response.Redirect(Request.RawUrl, true);
}
And this the ItemCommand event. I place a breakpoint on the first line, and the debugger never hits it.
protected void grdItems_ItemCommand(object source, DataGridCommandEventArgs e)
{
string item = "";
switch (e.CommandName.ToLower())
{
case "select":
item = e.Item.Cells[1].Text.Trim();
//todo: handle the selected data
break;
}
}
Thanks for any thoughts.
Don
I have a GridView control that uses a datatable for a data source. I have enabled paging on the control, and the GridView shows the number of rows I've specified as the PageSize. However, there is no paging navigation, so I have no way to change the page.
Question: How do I get the paging navigation to show?
GridView definition:
<asp:GridView runat="server" ID="gvResults" CssClass="report" DataKeyNames="LogId" AllowSorting="True" AllowPaging="True" PageSize="5" OnRowDataBound="gvResults_OnRowDataBound" OnPageIndexChanging="gvResults_OnPageIndexChanging"></asp:GridView>
C#:
//...stuff that gets data from database
DataTable dt = oDs.DataSet.Tables[0];
gvResults.DataSource = dt;
gvResults.DataBind();
NOTE: I've verified in debugger that the datatable dt has more than 100 rows
And the OnPageIndexChanging() event, based on the answer to this question, although it didn't work in my case (I'm not sure why it's necessary since the event shouldn't trigger until you attempt to go to the next page, which would require the paging navigation to show in the first place, right?):
protected void gvResults_OnPageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView gv = (GridView)sender;
DataView dv = gv.DataSource as DataView;
if (dv != null)
{
DataTable dt = dv.Table;
gv.DataSource = dt;
}
gv.PageIndex = e.NewPageIndex;
gv.DataBind();
}
Here is what I see:
I expect to see some way to page through the results.
I have also tried adding a PagerSettings to my GridView, like so:
<asp:GridView runat="server" ID="gvResults" CssClass="report" DataKeyNames="LogId" AllowSorting="True" AllowPaging="True" PageSize="5" OnRowDataBound="gvResults_OnRowDataBound" OnPageIndexChanging="gvResults_OnPageIndexChanging">
<PagerSettings Mode="NextPreviousFirstLast" FirstPageText="First" LastPageText="Last" NextPageText="Next" PreviousPageText="Previous" Position="Bottom"></PagerSettings>
</asp:GridView>
Here is what the rendered HTML looks like for that last row. I modified the css during runtime to expand the row so it's clear that the row is empty. There are no paging controls being hidden by css.
After much banging of head and gnashing of teeth, I finally figured this out.
I have another event that operates OnRowDataBound() which formats a particular column to HTML, and this conversion resulted in no paging controls when it operated on the footer row.
The solution was to check that the bound row is a DataRow before doing the conversion.
protected void gvResults_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (!(sender is GridView) || e.Row.RowType != DataControlRowType.DataRow) return;
//do stuff
}
And then happiness ensued:
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 have a formview and a nested gridview where i would like to be able to select the value of a specific cell when the row has been updated. I took the example code from the msdn site as it's close to what i want:
protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
GridView SprayGrid = (GridView)FormView1.FindControl("GridView1");
int Index = SprayGrid.EditIndex;
GridViewRow row = SprayGrid.Rows[Index];
TextBox message = (TextBox)FormView1.FindControl("TextBox1");
message.Text = row.Cells[4].Text;
}
However, for some reason this will only pick up the index of the cell, i.e. if i change the row.cells[0] i can see in my message box the index number if i want to see any other cell then the message is blank? Any ideas would be great.
Use DataKeys on the GridView, and instead of trying to set the TextBox value from the cell, set it from the DataKey.
In the ASPX:
<asp:GridView Id="GridView1" runat="server" DataKeyNames="SomeColumnName">
And in your row updating event:
TextBox message = (TextBox)FormView1.FindControl("TextBox1");
message.Text = SprayGrid.DataKeys[row.RowIndex]["SomeColumnName"].ToString();
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