Repeater won't let me access controls like buttons, dropdown, etc - asp.net

I'm using a repeater ListOfArticles and have controls inside it like ddlSizes and btnSelectArticle. Normally you can just double click the control and in the aspx.vb page you can specify an action. I have heard something about Findcontrol, but can't figure out or find much information that I understand. I don't want to sound like an ass, but I would really prefer help for the aspx.vb page and not in C# or Javascript.
An example of what I'm trying to do is, once you've clicked btnSelectArticle the label lblSelection receives the following values Amount: txtAmount - Size: ddlSizes.SelectedValue.
<asp:Repeater ID="rptListOfArticles" runat="server" DataSourceID="objdsArticleList">
<asp:DropDownList ID="ddlSizes" runat="server" AutoPostBack="True" DataSourceID="objdsSizes" DataTextField="SizeName" DataValueField="SizeID" OnSelectedIndexChanged="ddlSizes_SelectedIndexChanged" />
<asp:Button ID="btnSelect" runat="server" Text="Select" OnClick="btnSelect_OnClick" />
<asp:Label ID="lblSelection" runat="server" Text=""></asp:Label>
In the aspx.vb page I can only select this and my controls like ddlSizes and btnSelect aren't recognized.
Protected Sub rptListOfArticles_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles rptListOfArticles.ItemCommand
End Sub
Any help towards a solution would be great!

What you need to do is use the FindControl method to find the specific control in the selected repeater Item.
so an example would be (within the ItemCommand method)
Dim lblSelection as Label = CType(e.Item.FindControl("lblSelection"), Label)
lblSelection.Text = "Your Text"
Edit **
To Answer your questions in the comments:
Yes to access the SelectedValue of the ddlSize DropDown you will need to create this:
Dim ddlSize As DropDownList = Ctype(e.Item.FindControl("ddlSize"), DropDownList)
The Repeater will know when to call this method when any Buttons are Clicked within the Repeater. Add a CommandName to your buttons so that you can then control what happens in the ItemCommand method.
e.g.
<asp:Button id="btnDoSomething" runat="server" text="Run ItemCommand" CommandName="Command1" />
In the ItemCommand use the code:
If e.CommandName = "Command1" Then
' run your code
End If

You can handle the event of dropdownlist in ItemCommand Event. Event bubbling concept comes here actually the child control bubble the evenet up to its parent i.e repeater control so you can handle it in parent control event eventually
for more details HERE you will have indepth insight of all events of repeater

Related

How to determine which button caused postback

I have 2 button controls. When I click one i'm trying to determine which one caused a postback in the page load. How to do determine this?
What about using CommandName and CommandArgument has shown in this example. This way you can have just one handler.
<asp:Button id="Button1"
Text="Sort Ascending"
CommandName="Sort"
CommandArgument="Ascending"
OnCommand="CommandBtn_Click"
runat="server"/>
<asp:Button id="Button2"
Text="Sort Descending"
CommandName="Sort"
CommandArgument="Descending"
OnCommand="CommandBtn_Click"
runat="server"/>
Do you come from a Classic ASP background? When I first used ASP.NET, the same question occurred to me.
Consider an alternative approach:
Rather than detect the postback in the Form_Load, and then figure out what triggered it, create a specific event handler for each of your buttons. This is the whole point of Web Forms - so you can develop apps in very similar ways as you would Windows applications.
Really input with type button sends its value within post request. For example if you have you'll get in Post button-name=Quote like it's simple text input. So you can just check if post contains value for the button using code like following (sorry for my vb):
Dim isQuote As Boolean = HttpContext.Current.Request.Form(SubmitQuote.UniqueID) IsNot Nothing
so if it's not Nothing (null) then post has been sent by SubmitQuote button.
BTW for me HttpContext.Current.Request("__EVENTTARGET") didn't work either.
In my implementation there are several forms on my page; if a post-back was triggered by certain button controls further operations are necessary.
The controls are of the following type, which do not populate Request["__EVENTTARGET"]
Button (at the root of the form)
Image Button (nested within a Datagrid)
I determine if the following button controls instigated the post-back, by reviewing that the UniqueID of the control was passed to the form request within the Page_Load sub:
- ASP.NET:
<asp:Button ID="Button1" runat="server" />
<asp:Button ID="Button2" runat="server" />
To simply handle whether the following nested image button instigated the post-back I take advantage of the OnClientClick attribute which calls to a javascript function that will populate the value of a supplementary hidden field control with the UniqueID of the instigating control, then review the hidden control value similarly in the Page_Lode sub:
- ASP.NET:
<script type="text/javascript">
function SetSource(SourceID) {
var hiddenField = document.getElementById("<%=HiddenField1.ClientID%>");
hiddenField.value = SourceID;
}
</script>
<asp:HiddenField ID="HiddenField1" runat="server" Value="" />
<asp:ImageButton ID="ImageButton1" runat="server" OnClientClick="SetSource(this.id)" />
The Page_Load would then implement by some means:
-VB.NET
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
' ...
If Not Page.IsPostBack Then
If Not String.IsNullOrEmpty(Me.Page.Request.Form(Button1.UniqueID)) Then
' ...
ElseIf Not String.IsNullOrEmpty(Me.Page.Request.Form(Button2.UniqueID)) Then
' ...
ElseIf Not Me.Page.Request.Form(HiddenField1.UniqueID) Is Nothing _
And Not String.IsNullOrEmpty(Me.Page.Request.Form(HiddenField1.UniqueID)) Then
' ...
HiddenField1.Value = String.Empty
Else
' ...
End If
End If
End Sub
on page load check this
String ButtonID = Request["__EVENTTARGET"];

Cancel a cross-page postback?

I have a page that has several ListBoxes that have some cascading filtering based on the selected values using an AutoPostBack. The form takes all the selected values and generates an excel doc by cross-page posting to a different ASPX. The problem is, after clicking submit once, it will continually fire the cross-page postback every time a selection has changed.
<asp:ScriptManager runat="server" />
<asp:UpdatePanel UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:ListBox ID="ParentItems" runat="server" SelectionMode="Multiple" AutoPostBack="true"></asp:ListBox>
<asp:ListBox ID="ChildItems" runat="server" SelectionMode="Multiple" AutoPostBack="true"></asp:ListBox>
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="Submit" runat="server" PostBackUrl="~/AnotherPageThatGeneratesAnExcelDoc.aspx" />
How do I cancel the cross-page postback from the ListBoxes' SelectedIndexChanged events?
Here's the event in the codebehind:
Protected Sub ParentItems_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ParentItems.SelectedIndexChanged
'' do some filtering of the ChildItems ListBox
'' tried these but they do not work
''Submit.Enabled = False
''Submit.PostBackUrl = String.Empty
'' I also tried wrapping the button in a PlaceHolder and hiding/removing it, neither worked
''Buttons.Visible = False
''Buttons.Controls.Remove(Submit)
End Sub
This is my current solution using javascript. It works, but seems like a hack:
// using jQuery, add a click event that resets the form action
$("select[multiple]").click(function () {
this.form.action = this.form._initialAction;
});
Edit: adding a click event in the codebehind:
ParentItems.Attributes("onclick") = "this.form.action = this.form._initialAction;"
The problem is that using the PostbackUrl property resets the form action to a new URL, and your Ajax calls (or any subsequent postbacks) use whatever the current action of the form is.
Your solution doesn't work because the submit button isn't part of your UpdatePanel, so it never gets modified.
The easiest solution might be to move your Excel file generating code out of the page it's in, and into the page you're looking at, in the click handler of the button.
You also could probably include an iframe on the page you're looking at, and on submit, rather than going to a new page, set the source of the iframe to the Excel-generating page.
Both of these would avoid the need for using the PostbackUrl.

VB.NET AddHandler throwing Object reference not set

I have an ASP.NET page with code-behind in VB.NET. On the ASPX page I have a Repeater with an asp:ImageButton inside the repeater and I want to catch the clicks on the button. As far as I read I have to use FindControl and then handle the copy of the original control:
Codebehind:
Dim imagebutton1 As ImageButton = repeater.FindControl("btnImage1")
AddHandler imagebutton1.Command, AddressOf ReportTransfer
...
...
Protected Sub ReportTransfer(ByVal sender As ImageButton, ByVal args As CommandEventArgs)
...
End Sub
ASPX page:
<td>
<asp:ImageButton runat="server" ID="btnImage1" ImageUrl="~/images/icons/icon_small.png"
CommandArgument="3" />
</td>
</tr>
</ItemTemplate>
It throws "Object reference not set to an instance of an object" on the AddHandler line and I have no idea why it is doing it (I'm a bit new with VB.NET)
Thank you in advance
You should be handling ItemCommand event of the Repeater. In this event CommandSource is the image button. Either the CommandArgument or CommandName needs to indicate what command you actually want to perform. Setting the CommandArgument to 3, means each image button will have the same value.
The repeater.FindControl("btnImage1") is not going to work because each button's id is going to change.
Adding the handler is not correct.
Repeater.ItemCommand Event; Occurs when any button is clicked in the Repeater control; http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.itemcommand.aspx
You're getting "Object reference not set to an instance of an object" because imagebutton1 is null. Make sure you're actually finding a control before adding a handler.
AMissico is right, you want to actually subscribe to the Repeater's ItemCommand event, and use the CommandArgument to identify what row the user clicked on.

Accessing data associated with the RepeaterItem on Command execution

I want to access the data associated with the RepeaterItem in which an ItemCommand fired up. The scenario is, I have multiple RepeaterItems which Button controls in which the Command is set declaratively like this:
<asp:Repeater ID="Repeater3"
runat="server"
DataSource='<%# ClientManager.GetClientEmployees(Eval("ClientID")) %>'
OnItemCommand="RemoveEmployeeFromClient">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1"
runat="server"
Text="(x)"
CommandName="RemoveEmployeeFromClient">
</asp:LinkButton>
</ItemTemplate>
<SeparatorTemplate>,<br /></SeparatorTemplate>
</asp:Repeater>
The code behind is:
Protected Sub RemoveEmployeeFromClient(ByVal source As Object,
ByVal e As RepeaterCommandEventArgs)
' I want to access the data associated with
' the RepeaterItem which the Button was clicked.
End Sub
You can use e.Item.DataItem to get down to the data for the object, or you could store it in a hidden field.
Building on what Mitchel said, make sure you check to see that the RowType is DataRow. Don't want to do crap when you can't. The cast from e.Item.DataItem to your type would fail on the header or footer row.

Loading a value on the insert command of a detailsview

In a detailsview, how can I prepopulate one of the textboxes on the insertcommand (When the user clicks insert and the view is insert).
I think this would work for codebehind:
Dim txtBox As TextBox = FormView1.FindControl("txtbox")
txtbox.Text = "Whatever I want"
Is this right? What do I need in the aspx (not as sure)? Also, I'm assuming the server-side code will go in the itemcommand or insertcreating event.
I have typed this in VB.NET but I am using C# (I can do both so on a language agnostic forum I might type the problem in another language). I am also using a SqlDataSource, with my parameters and insert/delete/edit commands all created.
I am trying to generate a random GUID (using the GUID object), which will be prepopulated in the textbox.
Also, is the postbackurl property of a button not another way of preserving form state?
Thanks
I would update the field in the DetailsView to a TemplateField:
<asp:TemplateField>
<InsertItemTemplate>
<asp:TextBox ID="txtField" runat="server" Text='<%# Bind("GUID") %>'/>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="lblField" runat="server" Text='<%# Bind("GUID") %>'/>
</ItemTemplate>
</asp:TemplateField>
Then you have two options:
generate your GUID and insert into
your datasource. This may have to be done with SQL since you mentioned using SqlDataSource
remove the binding and access the controls from code in the
DataBound event of your DetailsView
Private Sub dv_DataBound(ByVal sender As Object, ByVal e As EventArgs) Handles dv.DataBound
dim txt as Textbox = dv.FindControl("txtField")
txt.Text = GenerateGUID()
End Sub
I'm guessing you need to use one of detailsview events.
Hook up to ItemCommand, ModeChanging or ModeChanged events and fill your value there.
I am doing something like this as well. I am hiding the DetailsView and showing it when the user clicks a button.
dvDetails.ChangeMode(DetailsViewMode.Insert)
pnlDetailMenu.Visible = True
Dim ColumnTextBox As TextBox
ColumnTextBox = dvDetails.Rows(0).Cells(1).Controls(0)
If Not ColumnTextBox Is Nothing Then
ColumnTextBox.Text = "Initial Value"
End If

Resources