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
}
Related
i'm gonna keep it short and simple
I'm a software engineering student in the 12th grade and as my final project I have decided to make a website. What the website is about doesn't really matter. The problem is this:
In the picture attached there is a textbox inside a templatefield inside that gridview. I need to get the value that the user writes inside. After you write a value you press Purchase. I've looked at similar questions and none offered a working solution. What happens is the value just disappears. I find the right control with FindControl, but the value gets deleted somehow. How do I know I am at the right control? I went to the client side and added to the asp:TextBox the following:
Text="5"
This works perfectly, so I know it gets to the right control but something makes it disappear. My gridview is being populated by a DataSet that is two datasets combined, and I put the Merge command and the DataSource and DataBind are both in if (!this.IsPostBack). I am completely lost and have no idea what to do, Help is much appreciated.The Picture of the Gridview
All the controls in a GridView are accessible by searching the correct row with FindControl. For that you can send the row number as a CommandArgument and use that in code behind. So first start by using OnCommand instead on OnClick and set the CommandArgument on the aspx page.
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Purchase" OnCommand="Button1_Command" CommandArgument='<%# Container.DataItemIndex %>' />
</ItemTemplate>
</asp:TemplateField>
And then in code behind
protected void Button1_Command(object sender, CommandEventArgs e)
{
//get the rownumber from the command argument
int rowIndex = Convert.ToInt32(e.CommandArgument);
//find the textbox in the corrext row with findcontrol
TextBox tb = GridView1.Rows[rowIndex].FindControl("TextBox1") as TextBox;
//get the value from the textbox
try
{
int numberOfTickets = Convert.ToInt32(tb.Text);
}
catch
{
//textbox is empty or not a number
}
}
Sounds a bit cluttered, but basically I have a databound repeater. On the ASP side, I have this:
<asp:Label ID="Label2" runat="server" Text='<%#Eval("uMessage") %>'></asp:Label>
I'm using the same template for 4 different datasets, and for 2 of them this should be a hyperlink and for the other 2 it shouldn't. So, I'm guessing you have to add a hyperlink programmatically in the code-behind? Has anyone ever done something like this?
Easiest way without all kinds of code-behind and therefor less code fragmentation, I would say you need a property that is set based on your condition prior to data binding.
protected bool LinkVisible { get; set; }
Then you just do this:
<asp:Label ID="Label2" runat="server" Text='<%#Eval("uMessage") %>' Visible="<%# !LinkVisible %>"></asp:Label>
<asp:HyperLink ID="Link" runat="server" Visible="<%# LinkVisible %>" ><%#Eval("uMessage") %></asp:HyperLink>
This sets the Visible for either the Label or the HyperLink. Visible false means it won't even get rendered. In your markup you can see that there will be a label or a hyperlink and no special things popup from the code behind.
You don't need to add the property LinkVisible, but can do the condition there too.
yes it is possible in code behind on DataItem bound
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label lbl = (Label)e.Row.FindControl("Label2");
if (lbl.Text == "your condition")
{
HyperLink yourLink = (HyperLink)e.Row.FindControl("yourID");
yourLink.enabled = false;
}
}
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.
I have the following control on my ASPX page:
<asp:TextBox ID="txtISBN13" runat="server" ClientIDMode="Static" />
I need to access this element without referring to it explicitly. Because this control does not yet exist during the Page_Load event, I have to access it later in the Page Life Cycle.
I've tried overriding the OnUnload event, because this is the final event, but I still can't access my control by either:
Control c = new Control();
c.FindControl("txtISBN13");
Or:
Control c = Page.FindControl("txtISBN13");
Am I overriding the incorrect event? Is ClientIDMode screwing with me? Even if I try similar code on a button click event, I get no luck. Do I need some kind of recursive FindControl? Should I be using Page.FindControl or Control.FindControl?
For this situation, I am unable to do:
this.txtISBN13.Text = "Foo";
Instead, I'll have a DataColumn (previousValue), and I need to find that control and set it's value. I'm trying:
string pendingID = String.Format("txt{0}", previousValue.ColumnName);
TextBox txt = new TextBox();
txt.ID = pendingID;
txt.Text = "Foo";
Assuming that the inputs are in some sort of container (PlaceHolder, Panel, etc.) you should be able to do this:
Markup:
<asp:PlaceHolder ID="PlaceHolder1" runat="server">
<asp:TextBox ID="txtISBN1" runat="server" />
<asp:TextBox ID="txtISBN2" runat="server" />
....
<asp:TextBox ID="txtISBN13" runat="server" />
</asp:PlaceHolder>
Code-behind:
TextBox txt = PlaceHolder1.Controls.OfType<TextBox>().FirstOrDefault(x => x.ID.ToUpper().Contains("ISBN13"));
if (txt != null)
{
txt.Text = row.Field<string>("ISBN13");
}
What container is your control in? You'll need to call containingControl.FindControl("txtISBN13"), or search recursively in the Page.Controls - C#, FindControl.
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.