Retrieving sibling control from Repeater on event - c#

I have a DropDownList on a repeater control, as well as a button.
The button is disabled until a valid item is selected on the DropDownList, when I want to enable the button. Unfortunately I can't seem to get to it.
Found the repeater by: (.As() method is an extension method for (object as T), just makes casting easier)
sender.As<Control>().NamingContainer.Parent.As<Repeater>()
However the Repeater I get back doesn't help me as the FindControl(string name) function isn't returning anything - and shows nothing useful in the watch window.
So, how can I get a sibling control (an ImageButton in this case) on a repeater from an event of another item on the repeater (DropDown_SelectedIndexChanged in this case)?
EDIT
I finally worked out
sender.As<ImageButton>().NamingContainer.As<RepeaterItem>().FindControl("ControlName")

I think i have the answer for your question:
1.-I create a repeater with the dropdownlist and button to do the tests:
<asp:Repeater ID="rp" runat="server">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" AutoPostBack="true" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
<asp:ListItem>3</asp:ListItem>
<asp:ListItem>4</asp:ListItem>
<asp:ListItem>5</asp:ListItem>
<asp:ListItem>6</asp:ListItem>
</asp:DropDownList>
<asp:ImageButton ID="Button1" runat="server" Enabled="False" />
</ItemTemplate>
</asp:Repeater>
I databind the repeater.
2.-I create the method DropDownList1_SelectedIndexChanged:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList control = (DropDownList)sender;
RepeaterItem rpItem = control.NamingContainer as RepeaterItem;
if (rpItem != null)
{
ImageButton btn = ((ImageButton)rpItem.FindControl("Button1"));
btn.Enabled = true;
}
}
The way to do it is to ask to the control, who is its Parent, that's to say, the RepeaterItem, or you can use NamingContainer (as I have written finally) and there you can ask about any control that is inside.

Related

How to find which control triggers the event inside a repeater

How to find which control event got triggered, for example, if there are 5 columns in the repeater if the 2nd checkbox or 3rd drop-down list causes the event. How to find which control event got triggered, so that the particular control related logic alone will be executed without disturbing other column controls.
The sample repeater code is attached as follows,
<asp:Repeater ID="rptTest" runat="server">
<ItemTemplate>
<td class="repeater-col">
<div>
<asp:TextBox ID="txt1" runat="server"></asp:TextBox>
</div>
<div>
<asp:DropDownList ID="ddl1" runat="server" OnSelectedIndexChanged="ddl1_SelectedIndexChanged" AutoPostBack="true">
</asp:DropDownList>
</div>
<div>
<asp:CheckBox ID="chk1" runat="server" OnCheckedChanged="chk1_CheckedChanged" AutoPostBack="true" />
</div>
</td>
</ItemTemplate>
</asp:Repeater>
There are lot more dependent controls presented inside the repeater. Based on the selection of the controls the data to the other controls are bound and processed. The logic bounded to the repeater will be handled on the respective events for example on chk1_CheckedChanged and ddl1_SelectedIndexChanged
Kindly help on this! Thanks in advance!
You can cast the sender back to the correct Control type. Then you can access it's properties. If you want to know which items the control was in, you can use the NamingContainer
protected void ddl1_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList drp = sender as DropDownList;
drp.BackColor = Color.Green;
RepeaterItem item = drp.NamingContainer as RepeaterItem;
int itemIndex = item.ItemIndex;
}

Access textbox within asp.net repeater

I have a nested asp repeater which is displaying all my items correctly. I have another div within the ItemTemplate of each repeater which submits content to my code behind.
<asp:Repeater runat="server" id="repeaterNote" OnItemDataBound="repeaterNote_ItemDataBound">
<ItemTemplate>
<div id="note" class="staff"><p><%# Eval("Content") %></p><ul>
<li><%# Eval("AddedDate") %></li><li>20:29</li>
<li><%# Eval("AddedByName") %></li><li>
Add comment</li></ul>
<div id="addComment<%# Eval("NoteID") %>" class="staff" style="display:none">
<asp:TextBox ID="notecommenttext" runat="server" rows="4"> </asp:TextBox>
<asp:Button ID="Button" runat="server" Text="Add" CommandArgument='<%# Eval("NoteID") %>' OnCommand="Add_Comment" />
</div>
</div>
When I submit the button I want to retrieve the content within the textbook "notecommenttext". There doesn't seem to be an easy way to do this. I have tried to set the ID of the textbook to the unique "NoteID" but it appears that cannot be done.
string uniqueNoteID = e.CommandArgument.ToString();
int parent = int.Parse(uniqueNoteID);
TextBox txtName = new TextBox();
foreach(RepeaterItem noteItem in repeaterNote.Items)
{
if (noteItem.ItemType == ListItemType.Item || noteItem.ItemType == ListItemType.AlternatingItem)
{
Notes rin = (Notes)noteItem.DataItem;
if (rin.RelativeNoteId == parent)
{
txtName = (TextBox)noteItem.FindControl("notecommenttext");
}
}
}
The snippet above is from the button callback "Add_Comment", repeaterNote is my top level Repeater id. It seems to have the correct number of RepeaterItems but the DataItem property is always null. I have added an inner foreach loop to iterate over my nested repeater. Again, this correctly identifies only one of the top level repeaters has a nested repeater element, but the DataItem is still null.
Any suggestions on how I can access the content from within the textbook of each repeater?
I think instead of setting OnCommand in your button, you should set OnItemCommand in your repeater to your event handler and just set the CommandName property in your button to an easily identifiable string. Then in the repeater's OnItemCommand event handler, you do a Select Case on e.CommandName, and if it's that button's CommandName that you set, you can use e.Item.FindControl("notecommenttext") to get your textbox control. Then get its content. When a control is in a repeater its ID gets a bunch of stuff appended to it so it is hard to find outside of a repeater event like ItemCommand.
I think your problem is that you are doing the Binding mecanism in your Page_Load() method without testing if (!IsPostback) That's why you dont find the result you want. Don't forget to set EnableViewState="False"
So you should move your Binding mecanism in Page_LoadComplete() method if you are in aspx page or add in your page load
if(!IsPostback)
{
//your binding mecanism
}

The Value Of A Check Box Is Empty Using An Enumeration Inside A Repeater (ASP.NET Web Forms)

I have a repeater and I set the value of an html check box control with the
value of an enumeration instead of hard-coding a magic number. When I try to
access the html check box control in the repeater's ItemCreated event handler,
the value is an empty string. Why is this and how can I fix it?
C# Code
protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e)
{
var myObject = e.Item.DataItem as MyObject;
if (myObject != null)
{
var checkBox = e.Item.FindControl("checkbox1") as HtmlInputCheckBox
// The value is empty!
var value = checkBox.Value;
}
}
Not Working
<asp:Repeater ID="Repeater1" OnItemCreated="Repeater1_ItemCreated" runat="server">
<ItemTemplate>
<input type="checkbox" id="checkbox1" value='<%# SomeEnum.Value %>' />
</ItemTemplate>
</asp:Repeater>
Working
<asp:Repeater ID="Repeater1" OnItemCreated="Repeater1_ItemCreated" runat="server">
<ItemTemplate>
<input type="checkbox" id="checkbox1" value="1" />
</ItemTemplate>
</asp:Repeater>
ItemCreated is triggered before ItemDataBound and also on every postback to recreate he controls even when the Repater is not databound again. So i would not use ItemCreated if you need to access the DataSource of any databound WebControl like Repeater.
Apart from that, make the checkbox runat=server(or use a ASP.NET CheckBox) if you want to find it on the server.

Bring up input form on same page with dropdownlist?

I'm brand new at this, using vs2010 with asp.net and c#, and I'm trying to use a button click event to display forms on my "Add Product" page (the forms will be textbox/label based for inputting data), using items from a dropdownlist of products. Which methods are available/is there a 'best practice' for this sort of thing? I've been fooling around with an if (Dropdownlist.SelectedIndexChanged) statement, but I'm not quite clear on why the syntax requires the SelectedIndexChanged method to preclude a += or -=. Thoughts?
The SelectedIndexChanged method has the += because you are adding an event handler to a specific elements event. Is the button you click on the Add Product page? If so for the OnClick event you could just set your form details based on the DropDownList SelectedItem or SelectedIndex. You may also need to wrap that panel in an UpdatePanel so that it can update visibility without reloading the whole page.
<asp:UpdatePanel ID="updateFormPanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="lblName" runat="server" Text="" />
<asp:TextBox ID="txtDetails" runat="server" Text="" />
//More TextBox's or whatever you want
</ContentTemplate>
</asp:UpdatePanel?
<asp:DropDownList ID="ddlProductCategory" runat="server" />
<asp:Button ID="btnAddProduct" runat="server" OnClick="AddProduct_Click" Text="Add Product" />
//Code File Behind
protected void AddProduct_Click(Object sender, EventArgs e)
{
lblName.Text = ddlProductCategory.SelectedItem.Text;
txtDetails.Text = ddlProductCategory.SelectedItem.Value;
}

DetailsView FindControl() returns null after some postbacks

I've been working for a long time with GridViews and DetailsViews, but yesterday I've come across a new scenario, which I quite do not understand.
I have a GridView with ImageButton (CommandName="Insert") which will change the mode of the DetailsView to Insert. Afterwards I'll look for a DropDownList inside that DetailsView and add some items dynamically. Works fine, but one first the first time I press that ImageButton. If I click on "Cancel" in the DetailsView and press the ImageButton again, the .FindControl() Method returns null. What life cycle problem am I facing here?
I've created this sample: (To make it run in your Visual Studio, just bind a DataSource to the DetailsView, otherwise it will not be rendered)
Markup:
<asp:GridView ID="gvCategory" runat="server" OnRowCommand="gvCategory_RowCommand">
<Columns>
</Columns>
<EmptyDataTemplate>
<asp:ImageButton ImageUrl="~/images/add.png" ID="ibAdd" runat="server" CommandName="Insert" />
</EmptyDataTemplate>
</asp:GridView>
<asp:DetailsView ID="dvCategory" runat="server" Width="150px" AutoGenerateRows="false"
AutoGenerateInsertButton="True" DataSourceID="LinqDataSource1">
<Fields>
<asp:TemplateField HeaderText="foo">
<InsertItemTemplate>
<asp:DropDownList ID="ddlCategory" runat="server" Width="150"></asp:DropDownList>
</InsertItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView><asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="WebApplication1.DataClasses1DataContext"
TableName="Categories"></asp:LinqDataSource>
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.gvCategory.DataBind();
}
}
protected void gvCategory_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Insert")
{
this.dvCategory.ChangeMode(DetailsViewMode.Insert);
DropDownList _ddlCat = (DropDownList)this.dvCategory.FindControl("ddlCategory");
if (_ddlCat != null)
{
_ddlCat.Items.Clear();
_ddlCat.Items.Add(new ListItem() { Text = "-- empty --", Value = "-1" });
}
}
}
I have also tried using a ItemTemplate, and not a InsertItemTemplate, but this results in the same. After using the ChangeMode-Method the DetailsView.CurrentMode == InsertMode. The only thing I can think of is, that the markup is already generated for the ItemTemplate and changing the Mode to InsertMode can't affect the rendered markup, or something like this.
Does anybody have a solution to this? =)
I think you are on the right track. It's hard to tell without seeing all of the code, but basically any time you change the rendering mode of a row in a repeater-type control you need to rebind it so that it's re-rendered. The fact that FindControl is returning NULL means only one thing: THE CONTROL IS NOT THERE. Which means it was not rendered. You can verify this by looking at the control hierarchy.
So, in your handler for Cancel are you rebinding?

Categories