I have an object that returns an IList which I'm getting from my ObjectDataSource and binding to a Gridview. All works fine if I just use standard binding, but I'm trying to customize my binding to set properties on a linkbutton as follows:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// extract the link button
LinkButton lnkViewMap = (LinkButton)e.Row.FindControl("lnkViewMap");
// grab the datarowview
System.Data.DataRowView row = (System.Data.DataRowView)e.Row.DataItem;
// set the onclientclick to fire our showMap javascript function,
// passing through the lat/longs
lnkViewMap.OnClientClick = string.Format("showMap({0}, {1}); return false;", row["Lat"], row["Long"]);
}
}
My error occurs where I am casting the e.Row.DataItem to a DataRowView. The code above is from Matt Berseth's awesome blog on Virtual Earth...which is what I am trying to implement here. Any ideas?
Set a breakpoint in the debugger and see what type e.Row.DataItem actually is.
It would only be a DataRowView if the DataSource you are setting on the grid is a DataView or DataTable. Otherwise it would be the element type of the collection.
Related
I have a datatable that I bind to a gridview. The columns are variable so I'd like to take advantage of AutoGeneratedColumns. I'd like to bind an image in certain condtions. What do I need to do?
void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
DataRowView drv = e.Row.DataItem as DataRowView;
if (drv != null)
drv[1] = new HtmlImage() { Src = "add.png" };
}
It sounds like the AutoGeneratedColumns property won't help you here because column types apply to the whole GridView; they are not calculated per-row.
You might be able to use a TemplateField with databinding to conditionally format the field for each row without writing any code.
If that doesn't get it done for you, I suppose you will have to write code. Bear in mind that the RowCreated event always fires (event on postback) when a row is created, but will only give you a non-null DataItem (e.Row.DataItem) when the GridView actually goes to its DataSource for databinding; if the GridView has cached its rendered state (in ViewState), the data item will be null. At that point, you would only be able to access the row's primary key fields by doing something like this: var keys = myGridView.DataKeys[rowIndex]; (The primary key fields are determined by the value you give the GridView's DataKeyNames property, and are stored in ViewState so that you can access them on postback.)
You would also be careful when modifying a column that is some type of DataBoundField (as most Fields are); since the RowDataBound event happens after the RowCreated event, any manual changes to the content of a row/cell you make in the RowCreated event handler are going to be clobbered by databinding when RowDataBound is fired.
That said, RowDataBound is probably the event you want.
The RowDataBound event will always give you a non-null DataItem, but only fires when real databinding happens (as opposed to "binding" from ViewState); so typically this event does not fire at all on postbacks. That's OK, though, since the GridView will remember its state for you.
If you must use code, it should probably look something like this:
//don't forget to attach this event handler, either in markup
//on the GridView control, in code (say, in the Page_Init event handler.)
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
//HtmlImage gives you a plain-vanilla <img> tag in the HTML.
//If you need to handle some server side events (such as Click)
//for the image, use a System.Web.UI.WebControls.Image control
//instead.
HtmlImage img = new HtmlImage() { Src = "path/to/image.jpg" };
e.Row.Cells[1].Controls.Add(img);
}
But, seriously, check out TemplateField first.
You can use RowDataBound event to process each row:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView drv = e.Row.DataItem as DataRowView;
if (drv != null)
{
// your code here...
}
}
}
For more information about this event see here
This should work, it uses the controls of the actual cell:
void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
HtmlImage img = new HtmlImage() { Src = "add.png" };
e.Row.Cells[1].Controls.Add(img);
}
I've comboBox in windows forms which I've bound to datasource, which is correctly returning Id associated with particular name in combobox whenever form loads.
private void PurchaseMaster_Load(object sender, EventArgs e)
{
DataTable dt = productMasterBAL.GetTable("Select * from productMaster");
comboBox1.DataSource = dt;
comboBox1.DisplayMember = "ProductName";
combBox1.ValueMember = "ProductId";
}
But whenever I select any value in Combobox I get:
NullReferenceException was unhandled. Object reference not set to an
instance of an object
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DataRowView row = comboBox1.SelectedValue as DataRowView;
MessageBox.Show(String.Format("{0}", row["ProductId"])); //This line is causing exception
}
Could anyone please tell how can I solve this problem?
I think you should be checking combobox1.SelectedItem rather than SelectedValue.
DataRowView row = combobox1.SelectedItem as DataRowView;
SelectedItem is the databound row which created that entry in the combobox. SelectedValue will be the ProductID of that row.
Or, you could try
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string productId = combobox1.SelectedValue as string;
if (productId != null)
{
MessageBox.Show(productId);
}
}
You should be checking for the values like this
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cmb = (ComboBox)sender;
MessageBox.Show(cmb.SelectedValue.ToString());// cmb.SelectedText
}
This should give you the selected Product Id in the combobox
The items in Combobox are stored as ObjectCollection and not exactly a DataRow or DataRowView as you seem to be expecting.
Have you debugged? Check that row isn't null? from msdn:
The as operator is like a cast operation. However, if the conversion
is not possible, as returns null instead of raising an exception.
Have you checked if this expression is valid as type?
May be row["ProductId"] is not a string field I think, so its returning an exception while formatting.
You are trying to cast PName.SelectedValue which is of type "String" to object DataRowView\ using 'safe-cast'. as returns null if object can't be cast to desired class. So, the actual mistake is in
DataRowView row = PName.SelectedValue as DataRowView;
Try direct cast with DataRowView row = (DataRowView)PName.SelectedValue, you'll definitely will get an error.
You should query your data source again to fetch data object.
Check out my generic solution on this thread:
c# loop through combobox where datasource is a datatable with text
Basically, you can call my function, telling it the type of each ComboBox Item, and it'll do the rest.
ComboBoxHelper.SetComboBoxSelectionByValue<EmployeeRecord>(comboBoxEmployees, someEmployeeID);
Hope this helps!
I have a GridView on my webpage whose DataSource is a DataTable which is populated at runtime. AllowSorting property of GridView is True. I have successfully implemented manual sorting for this GridView.
But I had to translate the webpage to other languages for which I used local resource files. I changed the Header text of GridView columns in RowDataBound event. Since then I'm unable to sort the GridView.
protected void GVSummaryTable_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.Cells.Count > 0)
{
//Translate header text
if (e.Row.RowType == DataControlRowType.Header)
{
e.Row.Cells[0].Text = GetLocalResourceObject("GVSummaryTableName").ToString();
e.Row.Cells[1].Text = GetLocalResourceObject("GVSummaryTableLoginLevel").ToString();
e.Row.Cells[2].Text = GetLocalResourceObject("GVSummaryTableLoginID").ToString();
e.Row.Cells[4].Text = GetLocalResourceObject("GVSummaryTableDate").ToString();
}
}
}
What should I do to enable sorting for the columns?
Any help would be appreciated. Thanks!
Changing the code to below solved the problem:
if (e.Row.RowType == DataControlRowType.Header)
{
LinkButton LnkHeaderText = e.Row.Cells[1].Controls[0] as LinkButton;
LnkHeaderText.Text = "Name";
}
I am not sure if the problem is related to the Header text since the sorting is normally done with the Sort Expression. Please, make sure you are also giving a value to this property when doing the Sorting. Hope this helps!
I have a gridview control which contains an image field. However, the image url is built from several fields in my returned dataset. How do you concatenate those fields together, and at which point do I do this so that I can pass that image url do my imagefield in my gridview? I am guessing it's on the RowDataBound but I don't know how to access each of the rows in my dataset?
Thanks.
I'm not sure what you are trying to concatenate without a code example, however I would perform the concatenation before binding the gridview and store it in a private member on the class so that you can access it later in the RowDataBound event.
You can use the row data bound event to find the control within that row and set its ImageUrl property.
private string m_ConcatUrl;
protected void gridView_RowDataBound(Object sender, GridViewRowEventArgs args)
{
if(args.Row.RowType == DataControlRowType.DataRow)
{
Image imgCtrl = (Image) args.Row.FindControl("imgCtrl");
imgCtrl.ImageUrl = m_ConcatUrl;
}
}
You can use RowDataBound event to set the cell value.
void YourGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
// You can set your cell value in this
e.Row.Cells[index] // use this to set the value in the cell
}
}
In .NET 4, it would be like this:
if (e.Row.RowType == DataControlRowType.DataRow)
{
string1 = e.Row.Cells[i].Text;
}
i is the index of the particular column you want to reference (e.g. Cells[0] is column 1).
I'm not sure if it's different in 3.5 but try that.
how to skip specific item in row bind event C#
You could
Filter the data via the SQL query.
Filter the data via a table select if binding to a datatable/dataset
Filter data via a DataView
Use the RowDataBound event
Edit ~ Here is how to use the RowDataBound
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
GridViewRow row = e.Row;
if (row.RowType == DataControlRowType.DataRow) {
//A value to check for
string myValue = DataBinder.Eval(e.Row.DataItem, "myColumn").ToString();
if ((myValue == "a")) {
//Hide the row
row.Visible = false;
}
}
}
I am not sure how this will affect your paging....if you do have one.