Getting subcontrol in Repeater - c#

I am using ASP.NET and C# on .NET 4 to develop a simple app. I have a repeater with an item template containing a few controls; one of them is a label that must be set depending on a complex calculation. I am using the OnItemDataBound event to compute the text and set the label's text in the code behind, like this:
protected void repRunResults_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
//capture current context.
Repeater repRunResults = (Repeater)sender;
Label laMessage = (Label)repRunResults.Controls[0].FindControl("laMessage");
DSScatterData.RunResultsRow rRunResults = (DSScatterData.RunResultsRow)((DataRowView)(e.Item.DataItem)).Row;
//show message if needed.
int iTotal = this.GetTotal(m_eStatus, rRunResults.MaxIterations, rRunResults.TargetLimit);
if(iTotal == 100)
{
laMessage.Text = "The computed total is 100.";
}
else
{
laMessage.Text = "The computed total is NOT 100.";
}
}
The data source for my repeater contains a few rows, so I would expect that each impression of the repeater would call the event handler and show the message according to the data in the associated row. However, I only get one message, which appears on the first repeater impression but matches the data for the last row in the data source.
It seems like every time the ItemDataBound event fires, the controls that my code captures are the same ones, so that I overwrite the message on every impression of the repeater. I have stepped through the code and this is what it is apparently happening.
Any idea why? And how to fix it?
Note. My repeater is nested inside another repeater. I don't think this should be relevant, but it might be.

You are grabbing the first one. You need to use the item that is being passed in like so:
protected void repRunResults_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
//capture current context.
Repeater repRunResults = (Repeater)sender;
Label laMessage = e.Item.FindControl("laMessage"); //<-- Used e.Item here
DSScatterData.RunResultsRow rRunResults = (DSScatterData.RunResultsRow)((DataRowView)(e.Item.DataItem)).Row;
//show message if needed.
int iTotal = this.GetTotal(m_eStatus, rRunResults.MaxIterations, rRunResults.TargetLimit);
if(iTotal == 100)
{
laMessage.Text = "The computed total is 100.";
}
else
{
laMessage.Text = "The computed total is NOT 100.";
}
}

Related

difference between dropdownlist and usercontrol with a dropdownlist

i like to get initial value to my DDL and write ddl1.Text="6" - it works fine..
i try to do the same to a DDL which is part of a simple usercontrol(3 DDLs which create a date) - this doesn't work!!!
in default.aspx i tried-
DateUserControl2.SetD("17");
DateUserControl2.SetM("7");
((DropDownList)DateUserControl2.Controls[4]).Text = "2003";
in DateUserControl.ascx.cs
i put all the listitems created in Page_Init and it works fine
the other methods
public void SetD(object d)
{
this.DropDownListDuc.Text = d + "";
}
public void SetM(object m)
{
this.DropDownListMuc.SelectedValue = m + "";
}
when i try to trace, i see that the methods are ok, but, for example,if d parameter is 4 and
this.DropDownListDuc.Text = 4 + "";
is performed, still NOTHING changes!!!
(again, the same line in a "simple" DDL,like DropDownList1.Text = "20"; changes the DDL to 20!!
changing a Label in the eser control works too. it is just a DDL_in_a_usercontrol problem
thanks!
Well, keep in mind that you are NOT allowed to have two controls with the same "id" on one page.
But, what then occurs if you drop the user control two times on the same web page?
I have a hotel edit UC.
So, I can do this:
Say this markup:
<uc1:UHotelEdit runat="server" ID="UHotelEdit"
MyTable ="tblHotelsA" />
<div style="clear:both;height:30px">
</div>
<uc1:UHotelEdit runat="server" ID="UHotelEdit2"
MyTable ="tblHotelsA" />
So, note we have TWO UC's on the page. UhotelEdit, and UhotelEdit2.
My page load code is this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
UHotelEdit.MyPk = 6;
UHotelEdit.LoadData();
UHotelEdit2.MyPk = 7;
UHotelEdit2.LoadData();
}
}
And now we have this:
So, in above, we have Hotel Name text box, first name, last name etc.
But, we are NOT allowed to have multiple "id" of the same control on the page.
So, how can/could I set the hotel name of the first control to Zoo, and Zoo2 for the 2nd one?
Well, all of the controls are "nested" inside of the UC.
This is quite much like a grid view, or whatever. So, you have two choices:
if several of the controls had to be "often" changed, then make a public property in the UC.
or, you can get/grab/pluck out the control name of the UC.
eg this:
protected void Button1_Click(object sender, EventArgs e)
{
TextBox txtHotel = UHotelEdit.FindControl("txtHotel") as TextBox;
TextBox txtHotel2 = UHotelEdit2.FindControl("txtHotel") as TextBox;
txtHotel.Text = "Zoo";
txtHotel2.Text = "Zoo2";
}
And thus we now have this:
But, if you had to "often" change the hotel name text box above?
Well, then add a public property to the UC, say like this:
public string HotelName
{
get { return txtHotel.Text; }
set { txtHotel.Text = value; }
}
And now our code becomes this:
protected void Button1_Click(object sender, EventArgs e)
{
UHotelEdit.HotelName = "Zoo";
UHotelEdit2.HotelName = "Zoo2";
}
So, for common or often controls to be changed? Setup a get/set for that control. For the rare and not common used?
Then you can use find control. Quite much you do the same to get a control out of repeater, listview, gridview etc. - you in general have to use find control for those nested controls.
Well, everything quite much works the same, but we have to prefix the control(s) with the name of the user control (id) we used when dropping on the page.
but, if you have JavaScript code, then how can I select the first one (hotel name) vs the 2nd one?
Turns out, all controls rendering inside of a UC will PREFIX the control with the name of the user control!!!
So, on the page you find two hotel text boxes,
UHotelEdit_txtHotel
UhotelEdit2_txtHotel
But, they are not exposed that way to code behind (just like controls nested in a listview or repeater also are not). but, they exist and jQuery selectors can be used against those controls.
In code behind, you have to use UC.findcontrol("txtHotel") to pluck out a reference to that control in the UC - since its nested inside.
So, if your UC has a dropdown list, and you want to with ease to change that value? Then add a PUBLIC method to the control that allows you do to this. So, while the controls inside are not exposed, you can with ease add a simple public method that allows you to change the drop down list value.

ASP.NET How do I check ever row in the gridview?

I want to add value into a Grid view via dropdownlist with a button.
I want the ddTN.SelectedItem.value in the Grid view to be unique. No duplication
How do I check every row for the ddTN.SelectedItem.value before adding a new ddTN.SelectedItem.value into the Grid view?
This are the codes that I have and it keep comparing the value with the first value in the gridview. Not the others.
I don't want to use a checkbox and such. All the example I found required using checkbox.
protected void Insert(object sender, EventArgs e)
{
int i = 0;
var p = 1;
DataControlFieldCell cell = GridView1.Rows[i].Cells[p] as DataControlFieldCell;
if (cell.Text != ddTN.SelectedItem.Value)
{
dt.Rows.Add(ddTN.SelectedValue, ddDuration.SelectedValue);
ViewState["Customers"] = dt;
this.BindGrid();
label.Text = "";
p++;
}
else
{
label.Text = "Exercise already inserted";
}
}
It looks like you were intending on looping over the items in the grid but you have forgotten the looping mechanism. In your code, it always only checks the first item because i is initialized to 0 and never changes.
Try using a looping mechanism like a for loop or a while loop. Or, if you know the items in the grid from the beginning, perhaps use a hash table for quickly checking if the selected item already exists.
Keep trying, you are almost there!

ASP .NET datalist does not recognize item in ItemDataBound event

I have a datalist and I'm trying to apply a css class to a panel inside some of the items like so:
protected void DataListProducts_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Header)
{
ProductsService service = new ProductsService();
DataTable dt = service.GetProduct(DataListProducts.DataKeys[e.Item.ItemIndex].ToString()).Tables[0];
if (((int)dt.Rows[0]["Quantity"]) <= 0)
{
Panel overlay = (Panel)DataListProducts.Items[e.Item.ItemIndex].FindControl("overlay");
overlay.CssClass = "soldOut";
}
}
}
When I try to run it I get the error
"Index was out of range. Must be non-negative and less than the size
of the collection."
I found out that the item index is equal to the item count of the datalist, which I think means the item hasn't been created yet, but shouldn't the ItemDataBound event fire after the item has been created and databound? Can someone please explain this to me?
Well, kinda solved it. I still don't know what the problem was, but iterating through the datalist with a foreach loop in a different function after the datalist has been databound gives me the desired effect.

How to set SkinID to the TextBox in the UserControl's CodeBehind File?

I am checking some condition in the GridView_RowCommand event. Based on the Condition I want to set SkinID or remove SkinID for the TextBox.
This is my Code:
if (dt.Rows[0]["D1Variable"].ToString() == "0")
{
txtMRVD1.Text = dt.Rows[0]["D1"].ToString();
txtMRVD1.ReadOnly = true;
txtMRVD1.SkinID = "txtreadonly";
}
else
{
txtMRVD1.Text = "";
txtMRVD1.ReadOnly = false;
}
But it throws the following error.
"The 'SkinId' property can only be set in or before the Page_PreInit event for static controls. For dynamic controls, set the property before adding it to the Controls collection."
How to solve this problem?
I would say, based on the error message, that you simply need to move that code to the Page_PreInit event.
However, as MSDN says: "If the request is a postback, the values of the controls have not yet been restored from view state. If you set a control property at this stage, its value might be overwritten in the next event."
You may need to get more creative in how you approach this - perhaps storing the information used to determine the skin id in Session. I suggest getting familiar, if you're not already, with the ASP.NET Page Life Cycle.
Here's an example that might work for you, or at least get you pointed in the right direction:
protected void Page_PreInit(object sender, EventArgs e)
{
if ((string)Session["D1Variable"] == "0")
{
txtMRVD1.SkinID = "txtreadonly";
}
}
You can then do the rest of your logic in the GridView RowCommand event.

DropdownList.selectedIndex always 0 (yes, I do have !isPostBack)

(Scroll down to bottom of post to find solution.)
Got a asp.net page which contains a
Datalist. Inside this datalist, there
is a template containing a
dropdownlist and each time the
datalist is filled with an item, a
ItemCreatedCommand is called. The
itemCreatedCommand is responsible for
databinding the dropdownlist.
I think the problem lies here, that
I'm using ItemCreatedCommand to
populate it - but the strange things
is that if I choose the color "green",
the page will autopostback, and I will
see that the dropdown is still on the
color green, but when trying to use
it's SelectedIndex, I always get 0...
protected void DataListProducts_ItemCreatedCommand(object
source, DataListItemEventArgs e)
var itemId = (String)DataListProducts.DataKeys[e.Item.ItemIndex];
var item = itemBLL.GetFullItem(itemId);
var DropDownListColor = (DropDownList)e.Item.FindControl("DropDownListColor");
//Also tried with :
//if(!isPostBack) {
DropDownListColor.DataSource = item.ColorList;
DropDownList.Color.Databind();
// } End !isPostBack)
Label1.test = DropDownListColor.SelectedIndex.toString();
// <- THIS IS ALWAYS 0! *grr*
I've narrowed down the code a bit for
viewing, but still you can see what
I'm trying to do :) The reason for
why I'm doing this, and not declaring
the datasource for the colors directly
i aspx-page, is that I need to run a
test if(showColors), but I do not want
to clutter up the html-page with code
that I feel should be in the code
behind-file.
EDIT: After trying to alter
SelectedIndexChange - I'm having a
"logical" confusion in my head now -
how am I to alter elements inside the
datalist? Since, as far as I know - I
do not have any way to check which of
the items in the datalist this
particular dropdownlist belongs to...
Or? I'm going to try out a few ways
and see what I end up with ;) But do
please post your thoughts on this
question :)
SOLUTION:
Either bubble the event to ItemCommand, or Handle the event, get the senders parent(which is a datalistItem and manipulate elements in there.
protected void DropDownListColor_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList dropDownListColor = (DropDownList)sender;
DataListItem dataListItem = (DataListItem)dropDownListColor.Parent;
var item = items[dataListItem.ItemIndex];
var color = item.ItemColor[dropDownListColor.SelectedIndex];
var LabelPrice = (Label)dataListItem.FindControl("LabelPrice");
LabelPrice.Text = color.Price;
}
When the DataList is data-bound, the AutoPostBack has not been handled yet, i.e. the values in the ItemCreated event are still the original values.
You need to handle the SelectedIndexChange event of the dropdown control.
Regarding your 2nd question:
I suggest you remove the AutoPostBack from the dropdown, add an "Update" button, and update the data in the button Click event.
The button can hold Command and CommandArgument values, so it's easy to associate with a database record.
some MSDN links with C# examples on bubbling
http://msdn.microsoft.com/en-us/library/system.web.ui.control.onbubbleevent.aspx
http://msdn.microsoft.com/en-us/library/aa719644(VS.71).aspx
http://msdn.microsoft.com/en-us/library/aa720044(VS.71).aspx
Thank You for your solution
protected void ddlOnSelectedIndexChanged(object sender, EventArgs e) {
try {
ModalPopupExtender1.Show();
if (ViewState["Colors"] != null) {
FillColors(ViewState["Colors"].ToString());
}
DropDownList dropDownListColor = (DropDownList)sender;
DataListItem dataListItem = (DataListItem)dropDownListColor.Parent;
Image image = (Image)dataListItem.FindControl("mdlImage");
Label ProductCode = (Label)dataListItem.FindControl("lblprdCode");
Label ProductName = (Label)dataListItem.FindControl("lblProdName");
DropDownList ddlQuantity = (DropDownList)dataListItem.FindControl("ddlQuantity");
Label ProductPrice = (Label)dataListItem.FindControl("lblProdPrice");
Label TotalPrice = (Label)dataListItem.FindControl("lblTotPrice");
//Label ProductPrice = (Label)dataListItem.FindControl("lblProdPrice");
} catch (Exception ex) {
}
}

Categories