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.
Related
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");
}
}
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.
I am adding to a List of DateTime objects on the server every time a date is selected on a Calender control by the client, and in turn highlighting all the selected dates on the control. I'm able to highlight (change back-color) of dates instantiated in the List on page load, and the first selected date by the client. However further date selections on the control are just changing which date is highlighted, ie. not highlighting more.
I had thought by adding the selected DateTime object to a list at runtime upon a selection and then adding each of them to the Calendars "selected dates" property will get around the problem of the calendar control clearing the SelectedDates property on selection of a new date. Debugging by printing all the dates within the dates List to a textbox show that the dates the list was instantiated with and the latest selection are only in the list, not previous selections. My question and what I think is the problem,
Can a List on the server be populated by actions from the client at runtime, and added to?
I am using ASP with C# .Net3.5 on VS2008.
Thanks
My Code
System.Collections.Generic.List dates;
protected void Page_Load(object sender, EventArgs e) {
this.dates = new List<DateTime>();
this.dates.Add(new DateTime(2009,12,2));
this.dates.Add(new DateTime(2009, 12, 3));
this.dates.Add(new DateTime(2009, 12, 16));
fillDates();
}
protected void AvailCalender_SelectionChanged(object sender, EventArgs e){
this.dates.Add(this.AvailCalender.SelectedDate);
foreach (DateTime date in this.dates)
{
this.AvailCalender.SelectedDates.Add(date);
this.displayText.Text = this.displayText.Text + date.ToShortDateString();
}
fillDates();
}
protected void fillDates()
{
foreach (DateTime dates in this.dates)
{
this.AvailCalender.SelectedDates.Add(dates);
}
this.AvailCalender.SelectedDayStyle.BackColor = System.Drawing.Color.Blue;
}
The List<DateTime> is getting created with each postback so it is not saving the previous selections. You need to persist it in some way like using ViewState, Session or storing it in a DB. Only create it the first time by using Page.IsPostBack to check if this is the first time the page has been hit.
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)
}
}
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