Accessing Object data in repeater - c#

I have a repeater on my asp.net web forms page.
The repeater data source is a list of "OrderLine" objects.
Each repeater item has a TextBox control that displays the quantity of the order line.
When the quantity in the textbox control is changed, there is an auto postback to recalculate the total and discount value properties of the OrderLine object.
My question is, is there a better way to access the object data directly instead of getting the index of the repeater item and using that to get the object list index like below?
I'd like to access the object directly if possible rather than create temporary variables.
protected void txtLineQuantity_TextChanged(object sender, EventArgs e)
{
RepeaterItem rItem = (RepeaterItem)((Control)sender).NamingContainer;
int i = rItem.ItemIndex;
decimal netPrice = OrderLines[i].NetPrice;
decimal netTotal = OrderLines[i].NetTotal;
int qty = OrderLines[i].Quantity;
decimal weight = OrderLines[i].Weight;
TextBox txtLineQuantity = (TextBox)rItem.FindControl("txtLineQuantity");
//... do calculations and bind data to repeater control
}
If i've missed any info that's needed please let me know...
Thanks

You can add a HiddenField control to RepeaterItem. Bind data to HiddenField.
ASP
<asp:Repeater runat="server" ID="repeater">
<ItemTemplate>
<asp:HiddenField ID="hiddenNetPrice" runat="server" Value='<%# Eval("NetPrice") %>' />
<!--Other Controls
</ItemTemplate>
</asp:Repeater>
C#
RepeaterItem rItem = (RepeaterItem)((Control)sender).NamingContainer;
var hiddenNetPrice= rItem.FindControl("hiddenNetPrice") as HiddenField;
var netPrice = hiddenNetPrice.Value;

Related

RadioButtonList with Repeater

I read a very good article here: (Displaying Data with the DataList and Repeater Controls (C#))
https://www.asp.net/web-forms/overview/data-access/displaying-data-with-the-datalist-and-repeater/displaying-data-with-the-datalist-and-repeater-controls-cs
I was trying to respond to the article author but am unable to add my account through Facebook, Twitter, etc at work to ask my question through the site, so I though I would ask here.
The example is very thorough and easy to follow, but I would like to see a RadioButtonList (say with Gender) x Male Female, showing the DB field value.
This would be a big help to compliment the article content
thx
First you need to add the RadioButtonList to the DataList or Repeater (they both work the same so I will provide only one example) and add the OnItemDataBound event.
<asp:DataList ID="DataList1" runat="server" OnItemDataBound="DataList1_ItemDataBound">
<ItemTemplate>
<asp:RadioButtonList ID="RadioButtonList1" runat="server"></asp:RadioButtonList>
</ItemTemplate>
</asp:DataList>
Code behind
protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
{
//find the control with findcontrol and cast back to a radiobuttonlist
RadioButtonList radioButtonList = e.Item.FindControl("RadioButtonList1") as RadioButtonList;
//add some listitems, usually filled from list or database
for (int i = 0; i < 5; i++)
{
radioButtonList.Items.Insert(i, new ListItem("ListItem " + i, i.ToString(), true));
}
//cast the dataitem to the datarowview
DataRowView row = e.Item.DataItem as DataRowView;
//set the correct radiobuttonvalue
radioButtonList.SelectedValue = row["dbValue"].ToString();
}

Accessing dynamically created HiddenField value in Code Behind

I have a HiddenField that I'm creating on a GridView's OnRowDataBound event:
var hF1 = new HiddenField();
e.Row.Cells[10].Controls.Add(hF1);
In JavaScript, I'm returning a value from a modal and setting the value on the HiddenField for that particular row, "hiddenField" being the ClientID of the HiddenField.
document.getElementById(hiddenField).value = settings;
Now, I have a Button.OnClick event where I need to capture that data for further processing, but I can't determine how I can retreive the data for the specific row.
foreach (SPGridViewRow dataRow in gvItems.Rows)
{
if (dataRow.RowType != DataControlRowType.DataRow) continue;
var mySettings = dataRow.... ?
How can I capture that value? Each value in the row's HiddenField control will be unique to that row. I'm also open to alternative storage of the temporary data held within this field on a per-row basis, just keep in mind that the data is returned from a JavaScript event.
Instead of creating the hidden field in the code behind I would set it up as a template column like this:
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField ID="myHiddenFieldID" runat="server"
Value='<%# Eval("SomeJSCLientID") %>' />
</ItemTemplate>
But that may not be necessary and you may be able to find your hidden control by doing this:
foreach (GridViewRow row in grid.Rows)
{
if (((HiddenField)row.FindControl("myHiddenFieldID")).Value)
{
//do your thing
}
}

data pager in listview Issue

I have a listview where in I placed datapager as follows.
I am using SQl datasource and binding the records to ListView.
asp:ListView runat="server" ID="ListView1" DataKeyNames="ProductId,GameName" DataSourceID="GameTable" OnItemCommand="On_Select_Item"
and datapager in the LayoutTemplate
And in the item template I am placing a button, when clicked it calls a method where i am trying to fetch DatakeyName values. It is working fine in first page when pager is given, However when moved to other page in the pager, it is throwing me an exception.
Here is the button click code,
protected void On_Select_Item(object sender, ListViewCommandEventArgs e)
{
if (String.Equals(e.CommandName, "AddtoCart"))
{
//checks if the user is logged in
if (User.Identity.IsAuthenticated)
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
DropDownList dl = e.Item.FindControl("DropDownList") as DropDownList;
String val="";
if (dl != null)
{
val = dl.SelectedValue; //Get the selected value from DropDownList
}
String price = Convert.ToString(e.CommandArgument).Trim(); //Get the price for the selected game.
-------------Exception is thrown at below line ---------
string ProductId =
ListView1.DataKeys[dataItem.DataItemIndex]["ProductId"].ToString(); //Product Id for the selected game.
string GameName = ListView1.DataKeys[dataItem.DataItemIndex]["GameName"].ToString(); //gamename
...............................
.............................
}
Define a grid first (you can change the control name to listView but the implementation is the same )
<asp:GridView runat="server" ID="grdResult"
CellPadding="2"
OnPageIndexChanging="grdResult_PageIndexChanging"
GridLines="None"
Width="100%"
AllowSorting="True"
AllowPaging="True"
Then in the bottom define a data source
<asp:SqlDataSource ID="sqlGridData" runat="server"></asp:SqlDataSource>
now in the code behind load your sqlGridData control with data (it accepts many parameters like datatable, odbcrecordset you can use .provider property mentioned here http://tinyurl.com/bllyjsz ) if you have static data them you even mention at the design time (as done here http://tinyurl.com/c8b6mbh)
private void BindDataGrid()
{
sqlGridData.Provider = dataReader;
grdResult.DataSourceID = "xmlGridData";
//grdResult.PageIndex = 0;
}
Try this and do let me know if you have any query.

Gridview Row Events not firing in UserControl

I've got a pretty strange problem with my usercontrols that I'm working with. I'm coding some user controls to be used in a DotNetNuke module.
Basically I have a UserControl on my page that holds some controls and then there is a Placeholder where I am loading in a UserControl that has a GridView placed in it.
Basically here is my page structure
<asp:Panel runat="server" ID="pnlServiceType" Visible="false">
<uc:ServiceType runat="server" ID="ServiceType" />
</asp:Panel>
Within that user control are some form elements and then the following:
<asp:PlaceHolder runat="server" ID="phServices" />
That placeholder then has a user control added to it like so:
<p class="header"><asp:Label runat="server" ID="lblServiceHeader" Font-Bold="true" /></p>
<asp:GridView runat="server" ID="gvServices" AlternatingRowStyle-BackColor="#eaeaea" BorderStyle="None" GridLines="None"
AutoGenerateColumns="false" CellPadding="6" Width="100%" EnableViewState="false" OnRowEditing="gvServices_RowEditing">
When the user picks something in the DropDownList, I'm clearing the controls out of the Placeholder, and re-adding just a single UserControl for the set of records for whatever type they've picked like so
_serviceID = e.Value;
//Clear the controls out of the placeholder
phServices.Controls.Clear();
//Reset the count of grids for the OnInit() method
Session["GridCount"] = 0;
if (e.Value != "NULL")
{
PopulateServicesGrid(_service.GetServicesByFormType(Convert.ToInt32(e.Value)));
}
else
{
PopulateServicesGrid(_service.GetServicesByClient(Convert.ToInt32(_client)));
}
And the PopulateServicesGrid method:
private void PopulateServicesGrid(List<NOAService> services)
{
//Creates a LINQ grouping based on the Billing Codes
//Allows a super easy creation of grids based on the grouped billing codes
var query = services.Select(service => service.BillingCode).Distinct();
foreach (string code in query)
{
var servicesByCode = services.Where(service => service.BillingCode == code).ToList();
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
Label lblServiceHeader = servicesGrid.FindControl("lblServiceHeader") as Label;
GridView gvServices = servicesGrid.FindControl("gvServices") as GridView;
phServices.Controls.Add(servicesGrid);
servicesGrid.ID = code;
lblServiceHeader.Text = servicesByCode[0].FormTypeName;
gvServices.DataSource = servicesByCode;
gvServices.DataBind();
Session["GridCount"] = phServices.Controls.Count;
}
}
And on my ServiceType UserControl, on the PageInit, I'm readding the ServiceGrid usercontrol so that my grids show up across postbacks and aren't lost from the Placeholder
void NOAServiceType_Init(object sender, EventArgs e)
{
for (int i = 0; i < Convert.ToInt32(Session["GridCount"]); i++)
{
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
phServices.Controls.Add(servicesGrid);
}
}
The grids populate successfully and everything seems to work just fine. But for some reason, on my GridView, I have a CommandField of
<asp:CommandField ShowEditButton="true" ItemStyle-HorizontalAlign="Right" EditText="Edit" UpdateText="Update"
EditImageUrl="~/images/LELModules/appbar.edit.rest.png" CancelImageUrl="~/images/LELModules/appbar.close.rest.png" UpdateImageUrl="~/images/LELModules/appbar.check.rest.png"
ButtonType="Image" CausesValidation="false" />
When I click my Edit command on the Grid row, nothing happens. My grid doesn't lose its rows, the control is still there, everything seems like it should be ok. The RowEditing event doesn't fire until I click it a second time.
Any idea why this might be occuring?
UPDATE: I've managed to figure out that my SelectedIndexChanged handlers are effectively resetting the DataSource on the Grid contained by the UserControl when they are readded to the PlaceHolder. When the CommandField (Edit) is clicked though, the Init fires for the UserControl that holds the placeholder
ServiceType UserControl < `Init` fires here
-Form elements
-Placeholder which holds
--UserControl with GridView
The Init method loads up new instances of the UserControl and adds them to the PlaceHolder, but the DataSource is null. With EnableViewState=true it looks like the data is still bound, but if I handle PreRender, I can see that the DataSource on my gvServices | null
Is it even possible to edit rows like this on a GridView that is being added dynamically to a PlaceHolder over and over?
FIXED I found out what the issue was after referring to this article
http://www.west-wind.com/weblog/posts/2006/Feb/24/Overriding-ClientID-and-UniqueID-on-ASPNET-controls
It got me thinking, what if the IDs were getting changed? The controls are way nested. So I went and put a watch on the GridView's ID, ClientID, and UniqueID just to see. When the Control is loaded on my Init handler, it's assigned a super generic ID when it's added.
private void PopulateServicesGrid(List<NOAService> services)
{
//Creates a LINQ grouping based on the Billing Codes
//Allows a super easy creation of grids based on the grouped billing codes
var query = services.Select(service => service.BillingCode).Distinct();
foreach (string code in query)
{
var servicesByCode = services.Where(service => service.BillingCode == code).ToList();
ServicesGrid servicesGrid = LoadControl("~/DesktopModules/LEL Modules/NOA/ServicesGrid.ascx") as ServicesGrid;
Label lblServiceHeader = servicesGrid.FindControl("lblServiceHeader") as Label;
GridView gvServices = servicesGrid.FindControl("gvServices") as GridView;
phServices.Controls.Add(servicesGrid);
**servicesGrid.ID = code;**
lblServiceHeader.Text = servicesByCode[0].FormTypeName;
gvServices.DataSource = servicesByCode;
gvServices.DataBind();
Session["GridCount"] = phServices.Controls.Count;
}
}
I was setting the ID as something else. So when I was hitting the Edit RowCommand on my grid, it was reloading the controls again on Init and the IDs were being changed back from my custom set code (T2020, pulled from my database) to the generic ID again, it didn't know how to fire the event.
I hope this helps someone as I've lost at least 12 hours fixing this problem.

page variable in a repeater

Hi I'm having a bit of an issue with a asp.net repeater
I'm building a categories carousel with the dynamic categories being output by a repeater.
Each item is a LinkButton control that passes an argument of the category id to the onItemClick handler.
a page variable is set by this handler to track what the selected category id is....
public String SelectedID
{
get
{
object o = this.ViewState["_SelectedID"];
if (o == null)
return "-1";
else
return (String)o;
}
set
{
this.ViewState["_SelectedID"] = value;
}
}
problem is that i cant seem to read this value while iterating through the repeater as follows...
<asp:Repeater ID="categoriesCarouselRepeater" runat="server"
onitemcommand="categoriesCarouselRepeater_ItemCommand">
<ItemTemplate>
<%#Convert.ToInt32(Eval("CategoryID")) == Convert.ToInt32(SelectedID) ? "<div class=\"selectedcategory\">":"<div>"%>
<asp:LinkButton ID="LinkButton1" CommandName="select_category" CommandArgument='<%#Eval("CategoryID")%>' runat="server"><img src="<%#Eval("imageSource")%>" alt="category" /><br />
</div>
</ItemTemplate>
</asp:Repeater>
calling <%=SelectedID%> in the item template works but when i try the following expression the value of SelectedID returns empty..
<%#Convert.ToInt32(Eval("CategoryID")) == Convert.ToInt32(SelectedID) ? "match" : "not a match"%>
the value is being set as follows...
protected void categoriesCarouselRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
SelectedID = e.CommandArgument.ToString();
}
Any ideas whats wrong here?
Within the categoriesCarouselRepeater_ItemCommand code you've shown, you're assigning the CommandArgument to a property called 'SelectedCategory'.
Should this not be assigning the property to the 'SelectedID' property instead?
** EDIT..
The problem I see is one of two scenarios:
1) You are not rebinding the repeater with each postback, and therefore the expression within your ItemTemplate is not being evaluated - The output from the repeater will remain unchanged with each postback.
OR
2) You are rebinding the repeater control with each postback, however, upon clicking on your LinkButton for the first time, the repeater control is re-binded PRIOR to the ItemCommand event handler firing, and therefore, the 'SelectedID' property has not been set until after the repeater has finished being output.
If you were to click on one of your LinkButtons a 2nd time, the previously selected ID would be in viewstate at the time of the repeater control contents being rendered, and therefore be one step behind in rendering which category has been clicked, and so on...

Categories

Resources