Equivalent of Eval("field") in ASP.NET Repeater ItemDataBound event? - asp.net

I want to do the equivalent of Eval("field") in an ASP.NET repeater ItemDataBound Event but am not sure what to cast e.Item.DataItem as. The data source type could vary as this is reusable code in a custom control. So how can I access a field in e.Item.DataItem by field name (a string)?
Ideally I want to do something like:
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
xxx item = (xxx)e.Item.DataItem;
string fieldValue = item("fieldname");
}
}

If you don't know what the type is at compile time your only option is to treat is as an object (which is the default return type for the DataItem property).
You could try using:
object item = DataBinder.Eval(e.Item.DataItem, "fieldname");
You're still stuck with an object at the end of that call, but (assuming the call is successful) you'll know that item has a property named fieldname. I don't know if that helps. Perhaps update your question with more detail about what you're trying to do.

instead of xxx item = (xxx)e.Item.DataItem;
write it:
var item = e.Item.DataItem;
or may be:
object item = e.Item.DataItem;

Related

Cannot find id of control inside gridview which inside another gridview

Can anyone help me on this?
I have a button(ImageButton1) inside a GridView (gvSdt), and gridview b is inside another Gridview (gvClass).
but it come out an error said "The name 'gvSdt' does not exist in the current context"
The code i used as below:
protected void gvSdt_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow row = gvSdt.SelectedRow;
int rowIndex = gvSdt.SelectedIndex;
string strValue = gvSdt.DataKeys[rowIndex].Value.ToString();
}
Since gvSdt is contained within another GridView, you won't be able to access it directly, as it is repeated content. Since gvSdt can exist multiple times, gvSdt would therefore refer to multiple GridViews.
This is made easy however, since you are using the SelectedIndexChanged event of the GridView in question. Notice the sender argument of the method. The object that gets passed there is actually the GridView. So just cast it as such.
protected void gvSdt_SelectedIndexChanged(object sender, EventArgs e)
{
GridView gvSdt = (GridView)sender;
GridViewRow row = gvSdt.SelectedRow;
int rowIndex = gvSdt.SelectedIndex;
string strValue = gvSdt.DataKeys[rowIndex].Value.ToString();
}

how bind DataList template field in asp.net

i want to bind a label -i created- in Datalist template to col -named "item"-in my dataSource
i used the following code after several trials
DataList2.DataSource = dt; // my DataSource
Label l1 = (Label)DataList2.FindControl("itemLabel");
l1.Text = dt.Rows[0]["item"].ToString();
DataList2.DataBind();
i got the following error at line '3' i am looking for the right expression
Object reference not set to an instance of an object.
any help would be appreciated..
The label is null since it's NamingConainer(used for FindControl) is not the DataList but one of it's DataListItems (a DataList is used for multiple items).
So you need to DataBind it first, then you can handle it's ItemDataBound event. There you are able to find the label and the underlying DataItem.
void Item_Bound(Object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Retrieve the Label control in the current DataListItem.
Label itemLabel= (Label)e.Item.FindControl("itemLabel");
DataRow row = ((DataRowView)e.Item.DataItem).Row;
String item = row.Field<string>("item");
itemLabel.Text = item;
}
}

Sorting a gridview using a datatable, and datasource that is an ArrayList

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.sorting.aspx
This article deals with creating a datatable first, then creating a gridview from it, to aid in sorting. My predicament is slightly different.
I have a Gridview, that on Page_Load, I set the datasource to an ArrayList, and bind.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.GridView1.DataSource = RequestManager.Instance.GetAllRequests();
this.GridView1.DataBind();
}
}
Now I would like to sort this GridView, so on the aspx page, I set AllowSorting="true", and OnSorting="GridView1_Sorting". So far, so good. I have the SortExpressions set in the BoundFields, and when I click on it, I know the _Sorting event is triggered.
Now, since this is a postback operation, I cannot simply cast the datasource of the gridview to a DataTable to sort. Saving to ViewState is an option, but I cannot figure out how to do it.
I would like to use the simple solution on this page, except for the DataTable not being available to me. Thanks for looking.
If you're able to target .NET v3.5, I recommend using Linq. In your _Sorting event handler, get the array list you did in the Page_Load and rebind it.
For example, if the type contained in the array list are MyType instances that have properties named Default and SomeField:
protected void Grid_Sorting(object sender, GridViewSortEventArgs e)
{
Func<MyType, object> keySelector;
if(e.SortExpresion == "SomeField")
{
keySelector = dataItem => dataItem.SomeField;
}
else
{
keySelector = dataItem => dataItem.Default;
}
ArrayList dataItems = RequestManager.Instance.GetAllRequests();
this.GridView1.DataSource = dataItems.OfType<MyType>().OrderBy(keySelector);
this.GridView1.DataBind();
}
That will get you started, then later inspect the sort expression to see if it ends with ASC or DESC and conditionally call .OrderByDescending(keySelector).
Finally, I don't recommend stashing the list in ViewState, as the ObjectStateFormatter is only optimized for a handful of types. http://msdn.microsoft.com/en-us/library/system.web.ui.objectstateformatter.aspx
Maybe consider ASP.NET cache instead.

Getting a column name in a Repeater in OnItemCreated

I am working on a Repeater that reads from a table with a layout something like:
string Title
string Location
bool Water
bool Sewer
bool Picnic_Table
bool On_Beach
...
I am creating a list of amenities for each "Title" so I need to loop through the columns and get a list of amenities for each Title (or site). Optimally, I have a loop to go through the list. Something like
for each column
if column is not Title or Location
Append to StringBuilder "column name"
How do I get that column name to do the comparisons?
Here's how to get the column name in the OnItemCreated event of the Repeater control:
protected void rptOnItemCreated_OnItemCreated(object sender, RepeaterItemEventArgs e)
{
string columnName = string.Empty;
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRowView drv = (DataRowView)e.Item.DataItem;
DataRow dr = drv.Row;
foreach (DataColumn dc in dr.Table.Columns)
{
// Do what you want with the column name
columnName = dc.ColumnName;
}
}
}
Repeater is not a table-based control, so that's going to be hard from the server-side. What you can do is programmably create a table, or use the Grid control. Or, try to make the table a server-side control, and see if that works well with the repeater (I don't think it will). Or, if you can say ignore the first two columns, make the table row within the repeater item a server-side row as in , and use FindControl to find the item and do something with it. You would have to work with the cell index though, to show/hide cells within the column.
HTH.

ASP.net list of dropdownlists - similar to Access continuous form

What I'm looking for is a way to mimic the MS-Access style continuous form within asp.net. In one particular case, I want a control, bound to a datasource which returns a dropdownlist for each row, bound to the value within the datasource. Any change to any of the dropdownlists' would perform an update to the database instantly.
I have got halfway to achieving this using a repeater control, with the DropDownList.SelectedValue assigned within the Repeater.ItemDataBound event.
But now, supposing I add an OnSelectedIndexChanged event to the DropDownList - how would I then query the repeater to know which row I was on (to get the primary key value, for example)
I'm not sure this can be done easily.. so the question is what should I really be doing? I don't want to use a GridView that requires me to select a row to edit.. I just want to have the dropdownlists autopostback for any updates.
Hope that's clear?!
Cheers! :D
For examples sake, lets say we are binding to a custom class called Record
public class Record
{
public int Id;
public string Value;
}
If you put custom logic on the Repeater.OnItemCreated event you can attach the primary key to the id of the drop down list
protected void Repeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if (!(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem))
return;
var dataItem = e.Item.DataItem as Record;
if (dataItem == null) return;
var dropdown = e.Item.FindControl("myDropDown") as DropDownList;
if (dropdown == null) return;
dropdown.ID = dropdown.ID + dataItem.Id;
}
Then on the SelectedIndexChange, you can pull the id off of the dropdown that fired the event.
protected void SelectedIndexChanged(object sender, EventArgs e)
{
var dropdown = sender as DropDownList;
if (dropdown == null) return;
var stringId = dropdown.ID.Replace("myDropDown", "");
int id;
if (Int32.TryParse(stringId, out id))
{
updateRecord(id, dropdown.SelectedValue);
}
}
It's very much an ugly hack, but it should allow you to do what you want.
Easiest way to tackle this would be to mimic the Access continuous form ASP.NET style. Which would be to make a UserControl to handle the row-level UI, then put said UserControl in a repeater.

Resources