Accessing parent controls from a user control - asp.net

I have a RadTabStrip on my parent.aspx page:
<telerik:RadTabStrip ID="rm_comparable" runat="server"
MultiPageID="Data"
CausesValidation="False" Enabled="false"
Height="100%"
ShowBaseLine="True">
<Tabs>
<telerik:RadTab runat="server" Text="Property" Selected="True" >
</telerik:RadTab>
<telerik:RadTab runat="server" Text="Sales" >
</telerik:RadTab>
</Tabs>
</telerik:RadTabStrip>
<telerik:RadMultiPage ID="Data" runat="server" SelectedIndex="0">
<telerik:RadPageView ID="mainData" runat="server">
<uc1:propertyData runat="server" ID="propertyData"/>
</telerik:RadPageView>
<telerik:RadPageView ID="salesData" runat="server">
<uc1:salesRecords ID="salesRecords" runat="server" />
</telerik:RadPageView>
</telerik:RadMultiPage>
and use this code to try to change the control.
Private Sub enableTabStrip()
Dim myTabControl As RadTabStrip = DirectCast(Me.Parent.FindControl("rm_comparable"), RadTabStrip)
myTabControl.Enabled = True
End Sub
When I call the code when the page loads the tab strip is then enabled.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
enableTabStrip()
End If
End Sub
When I move the code I am calling out of the page load event, my RadTabStrip doesn't become available to the users as it did when I called the event in the page load.
Protected Sub btn_addAppraisal_Click(sender As Object, e As EventArgs) Handles btn_addAppraisal.Click
enableTabStrip()
End Sub
I am wondering why this functionality will only work in the page load event.

Related

Button on usercontroll doesn't fire / raise event

i have a usercontroll with two buttons and i want to get the raiseevent in the page where i call the usercontrol. Everything works fine except that i can't catch the event when i click the button on the user contol.
my markup for the uc:
<%# Control Language="VB" AutoEventWireup="false" CodeFile="MsgBox.ascx.vb" Inherits="MsgBox" ClassName="MsgBox" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="act" %>
<style type="text/css">
.Modal_trans {
opacity: 0.8;
filter: alpha(opacity=60);
}
</style>
<link rel="stylesheet" type="text/css" href="../Styles/StyleSheet.css" />"
<asp:Panel ID="PopPanel" runat="server"
Width="500px" Height="50px" DefaultButton="ok" Style="overflow:hidden;" CssClass="ModalGrid">
<table style="width: 100%; border-collapse: collapse; border: 0px;">
<tr id="boxheader" runat="server" style="cursor: move;">
<th colspan="2" style="padding-left: 10px; padding-top: 3px; padding-bottom: 3px;">
<asp:Label ID="lblTitle" runat="server" Text="Help"></asp:Label>
</th>
</tr>
<tr>
<td>
<asp:Image ID="Image" runat="server" ImageUrl="../images/info.png" />
</td>
<td style="padding: 10px; width: 220px;">
<div style="width: 295px; height:70px;"">
<asp:Label ID="lblMsg" runat="server" BackColor="#CCCCCC" />
</div>
</td>
</tr>
<tr>
<th colspan="2" style="padding-right: 20px; padding-top: 7px; padding-bottom: 7px;"" >
<asp:LinkButton ID="LinkButton1" runat="server" Style="display:none" ></asp:LinkButton>
<asp:Button ID="ok" runat="server" Text="Ok" Width="80px" />
<asp:Button ID="no" runat="server" Text="No / Cancel" Width="80px" Visible="False" />
</th>
</tr>
</table>
</asp:Panel>
<act:ModalPopupExtender ID="PopUp" runat="server" Enabled="True"
PopupControlID="PopPanel" TargetControlID="LinkButton1" BackgroundCssClass="Modal_trans"
OkControlID="ok" PopupDragHandleControlID="boxheader" Y="0" DropShadow="True">
<Animations>
<OnShown>
<Sequence AnimationTarget="PopPanel">
<Parallel Duration=".5" Fps="25">
<Move Horizontal="-175" Vertical="200" />
<Resize Width="350" Height="142"/>
<FadeIn />
</Parallel>
</Sequence>
</OnShown>
<OnHiding>
<Sequence AnimationTarget="PopPanel">
<%-- Scale the flyout down to 5% to make it disappear --%>
<Parallel Duration=".75" Fps="25">
<Scale ScaleFactor="0.05" Center="true" ScaleFont="true" FontUnit="px" />
<FadeOut />
</Parallel>
<%-- Reset the styles on the info box --%>
<StyleAction Attribute="display" Value="none"/>
<StyleAction Attribute="width" Value="350px"/>
<StyleAction Attribute="height" Value=""/>
<StyleAction Attribute="fontSize" Value="12px"/>
<%-- Re-enable the button --%>
<EnableAction Enabled="true" AnimationTarget="ok" />
</Sequence>
</OnHiding>
</Animations>
</act:ModalPopupExtender>
and the code behind
Partial Class MsgBox
Inherits System.Web.UI.UserControl
Public Shared IconInfo, IconExec, IconQues, IconError As Object
Public Property MsgText As String
Get
Return lblMsg.Text
End Get
Set(ByVal value As String)
lblMsg.Text = value
End Set
End Property
Public Event MsgButtonClick(ByVal buttonName As String)
Protected Sub MsgButtonOKClick(ByVal sender As Object, ByVal e As EventArgs) Handles ok.Click
RaiseEvent MsgButtonClick("ok")
End Sub
Protected Sub MsgButtonDenyClick(ByVal sender As Object, ByVal e As EventArgs) Handles no.Click
RaiseEvent MsgButtonClick("no")
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
IconInfo = "Show Information Icon"
IconExec = "Show Warning Icon"
IconQues = "Show Question Icon"
IconError = "Show Error Icon"
End Sub
Public Sub Pop(Optional ByVal Message As String = "", Optional ByVal Mode As Object = "IconInfo", Optional ByVal Title As String = "Info Message")
no.Visible = False
ok.Text = "Ok"
If Title <> "" Then
lblTitle.Text = Title
End If
Select Case Mode
Case "IconInfo"
Image.ImageUrl = "../images/info.png"
no.Visible = False
ok.Text = "Ok"
lblTitle.Text = "Info"
Case "IconExec"
Image.ImageUrl = "../images/exc.png"
no.Visible = False
ok.Text = "Ok"
lblTitle.Text = "Warning"
Case "IconQues"
Image.ImageUrl = "../images/ques.png"
no.Visible = True
ok.Text = "Yes" lblTitle.Text = "Question"
Case "IconError"
Image.ImageUrl = "../images/error.png"
no.Visible = False
ok.Text = "Ok"
lblTitle.Text = "Error"
End Select
PopUp.Show()
End Sub
Protected Sub No_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles no.Click
PopUp.Hide()
End Sub
Tested also with the variation
Public Event MsgButtonClick As EventHandler
Protected Sub MsgButtonOKClick(ByVal sender As Object, ByVal e As EventArgs) Handles ok.Click
RaiseEvent MsgButtonClick(sender, e)
End Sub
Protected Sub MsgButtonDenyClick(ByVal sender As Object, ByVal e As EventArgs) Handles no.Click
RaiseEvent MsgButtonClick(sender, e)
End Sub
In my page, it's a contetpage of a master page with update panel i try to catch the event with following in the code behind
Protected Sub test() Handles PopMsg.MsgButtonClick
Response.Write("Done")
End Sub
In the markup on the page i have placed the controldirectly behind the ContentTemplate of the UpdatePanel
<msg:PopInfoMsg ID="PopMsg" runat="server" />
And call the UC with a button click
Protected Sub HelpMsg()
PopMsg.MsgText = "My first Test<br/> Cheers<br/>"
PopMsg.Pop("", "IconInfo", "Info")
End Sub
The control open as expected, but when clicking the "OK" button the control close without an event.
In VS i tried to debug at the Button Click but the code doesn't run to this point.
Where i'am wrong? Confusing me the last days...
Cheers, Alex

Button click event not fired after moving it to the asp:content

I just moved the button from html to the asp:content because I use master page :
<asp:content id="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div>
<asp:CustomValidator ID="CustomValidator1" runat="server"
ErrorMessage="CustomValidator"></asp:CustomValidator>
<br />
<asp:FileUpload ID="FileUpload1" runat="server" />
<br />
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
<br />
<asp:Button ID="Button1" runat="server" Text="Upload" />
</div>
</asp:content>
The following code was working before I moved it, now the click event is not getting fired :
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
And it gave me an error (This error didn't occur before):
Handles clause requires a WithEvents variable defined in the containing type or one of its base types.
So I added the below line of code :
Private WithEvents Button1 As Button
But still, the button1 is never fired.
Please kindly help me.
The ContentPlaceHolder is a different NamingContainer than the Page(it implements INamingContainer), so it's not initialized automatically from ASP.NET if you declare the variable Private WithEvents Button1 As Button.
You have to attach the event handler declaratively (or programmatically from codebehind):
<asp:Button ID="Button1" OnClick="Button1_Click" runat="server" Text="Upload" />
and remove the Handles clause, the method must now be at least Protected:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
End Sub

General Function

in a project I am working on I have TabContainer (AJAX.NET) have many tabPanels all of them are doing the same function BUT each on on a different Table
let me give a sample :
<asp:TabContainer ID="TabContainer3" runat="server" ActiveTabIndex="0" BorderStyle="None"
BorderWidth="0" CssClass="MyTabStyle" Width="625px">
<asp:TabPanel ID="TabPanel1" runat="server">
<HeaderTemplate>
Tab_x
</HeaderTemplate>
<ContentTemplate>
<asp:TextBox ID="txt_x" runat="server"></asp:TextBox>
<asp:Button ID="btnx" runat="server" Text="Button" />
</ContentTemplate>
</asp:TabPanel>
<asp:TabPanel ID="TabPanel2" runat="server">
<HeaderTemplate>
Tab_y
</HeaderTemplate>
<ContentTemplate>
<asp:TextBox ID="txt_y" runat="server"></asp:TextBox>
<asp:Button ID="btny" runat="server" Text="Button" />
</ContentTemplate>
</asp:TabPanel>
</asp:TabContainer>
Code behind (VB.NET)
Protected Sub btnx_Click(sender As Object, e As System.EventArgs) Handles btnx.Click
SaveText_x(txt_x.Text)
End Sub
Protected Sub btny_Click(sender As Object, e As System.EventArgs) Handles btny.Click
SaveText_y(txt_y.Text)
End Sub
is there a way to create general Sub or Function so if I clicked btnx function Save_x(txt_x.Text) be called
and when I click btny function Save_y(txt_y.Text) be called ?
You can assign multiple buttons to have the same click handler with the following code :
Protected Sub btn_Click(sender As Object, e As System.EventArgs) Handles btnx.Click, btny.Click
Dim btn As Button = CType(sender, Button)
If btn.ID = "btnx" Then
SaveText_x(txt_x.Text)
ElseIf btn.ID = "btny" Then
SaveText_y(txt_y.Text)
End If
End Sub
Both btnx and btny will both fire this Sub and it will check the button that sent it to see which method to call.
1)Made user control with public string property. use view state to store value of that property.
2)Add that user control into your tabs set that property with values like "X" or "Y" or any.
3)On button click check that property with if .. else if .. else or by switch statement and call your SaveText functions variants.

How do you disable all of the controls inside panel's but enable some specified controls?

I have asp:panel with some controls, the mark-up as below
<asp:panel id="panel1" runat="server">
<asp:Label runat="server" Text="aaaa"></asp:Label>
<asp:Label runat="server" Text="bbbb"></asp:Label>
<asp:Label runat="server" Text="cccc"></asp:Label>
<asp:TextBox runat="server" ID="txt1"></asp:TextBox>
<asp:TextBox runat="server" ID="txt2"></asp:TextBox>
<asp:ImageButton ID="ibtn1" runat="server"/>
<asp:ImageButton ID="ibtn2" runat="server"/>
</asp:panel>
Now I want to disable all the controls, but enabling ibtn1 and ibtn2
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
panel1.Enabled = False
End Sub
Protected Sub Page_PreRender(sender As Object, e As System.EventArgs) Handles Me.PreRender
ibtn1.Enabled = True
ibtn2.Enabled = True
End Sub
All of the controls are disabled, that's great, but not for ibtn1 and ibtn 2.
Then, I have tried this method instead
Public Sub lDisableAllChildControls(ByRef p As WebControl)
For Each c As System.Web.UI.WebControls.WebControl In p.Controls
c.Enabled = False
'recurse
lDisableAllChildControls(c)
Next
End Sub
but it gave me this error:
Unable to cast object of type 'System.Web.UI.LiteralControl' to type
'System.Web.UI.WebControls.WebControl'
Does anyone has any idea to make this work? Thanks!
you replace with Control, because your label is litteral
For Each c As System.Web.UI.Control.Control In p.Controls
Next

Adding PostBackTriggers and AsyncPostBackTriggers to UpdatePanel for dynamically-generated grandchild controls

I have a page with a ScriptManager, a generic HTML drop-down list (<select>), and an UpdatePanel. The UpdatePanel contains a PlaceHolder (for now). During Page_Load, a number of user controls are added to the PlaceHolder (really, it's several instances of the same user control). The number to add is not known until the page loads, so they do need to be loaded dynamically. The drop-down list is populated with the same number of menu items, and there is javascript on the page also (using jQuery) to show only one of the controls at a time depending on the state of the drop-down list.
Each user control has two buttons that should generate an asynchronous postback, a drop-down list that should generate an asynchronous postback on a change in selected value, and a button that should generate a synchronous postback. If I was not generating the controls dynamically, and if there was only one control, the structure would be something like:
<asp:UpdatePanel ID="myUpdatePanel" runat="server" UpdateMode="Conditional"
ChildrenAsTriggers="false">
<ContentTemplate>
<asp:TextBox ID="textBox1" runat="server" />
<asp:TextBox ID="textBox2" runat="server" />
<asp:Button ID="asyncButton1" runat="server" Text="Button1"
onclick="asyncButton1_Click" />
<asp:DropDownList ID="asyncDropDown" ruant="server" AutoPostBack="true"
OnSelectedIndexChanged="asyncDropDown_SelectedIndexChanged" />
<asp:Button ID="asyncButton2" runat="server" Text="Button2"
OnClick="asyncButton2_Click" />
<asp:Button ID="syncButton" runat="server" Text="SyncButton"
OnClick="syncButton_Click" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="asyncButton1" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="asyncButton2" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="asyncDropDown"
EventName="SelectedIndexChanged" />
<asp:PostBackTrigger ControlID="syncButton" />
</Triggers>
</asp:UpdatePanel>
Of course, all the controls inside the ContentTemplate would actually be part of each user control.
Adding the triggers on the server side does not seem to work because no ControlID seems to help the UpdatePanel find the relevant controls. I can use either the control's ID or the control's UniqueID, and it does not work, and I get an error along the lines of
A control with ID 'ctl00$ContentPlaceHolder1$ctl01$asyncButton1' could not be
found for the trigger in UpdatePanel 'myUpdatePanel'.
So, I wonder if I need to register the triggers in the client instead using ASP.NET Ajax. I found this page that basically explains how. However, I do not know how to get the EventName taken into consideration. The examples I have seen so far have merely been adding button clicks, but I don't know how to handle the SelectedIndexChanged event from the DropDownList.
Any help here? Are there examples out there I have missed? It doesn't help, of course, that the method in the link I gave appears to be "unofficial," so I don't see any MSDN documents on the subject.
Thanks!
My suggestion would be to pull all your controls inclusive this UpdatePanel out of this UpdatePanel into an UserControl. Define events in your usercontrol that are raised when the buttons are clicked or the Dropdown's selected index get changed. Handle these events in your page that holds the Placeholder(in a single UpdatePanel,conditional,without triggers). Call the Update-method of the main update panel manually if you add UserControls.
To clarify what i mean have a look at following example:
Main-page aspx:
<asp:UpdatePanel ID="Upd1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
Codebehind:
Private Property UserControlCount() As Int32
Get
If ViewState("UserControlCount") Is Nothing Then
ViewState("UserControlCount") = 1
End If
Return DirectCast(ViewState("UserControlCount"), Int32)
End Get
Set(ByVal value As Int32)
ViewState("UserControlCount") = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
recreateUserControls()
End Sub
Private Sub recreateUserControls()
For i As Int32 = 1 To Me.UserControlCount
Dim uc As DynamicControls = DirectCast(Me.LoadControl("DynamicControls.ascx"), DynamicControls)
uc.ID = "DynamicControls_" & i
Addhandlers(uc)
Me.PlaceHolder1.Controls.Add(uc)
Next
End Sub
Private Sub Addhandlers(ByVal uc As DynamicControls)
AddHandler uc.asyncButton1Clicked, AddressOf ucAsyncButton1Clicked
AddHandler uc.asyncButton2Clicked, AddressOf ucAsyncButton2Clicked
AddHandler uc.syncButtonClicked, AddressOf ucSyncButtonClicked
AddHandler uc.asyncDropDownSelectedIndexChanged, AddressOf ucAsyncDropDownSelectedIndexChanged
End Sub
Private Sub addUserControl()
Me.UserControlCount += 1
Dim uc As DynamicControls = DirectCast(Me.LoadControl("DynamicControls.ascx"), DynamicControls)
uc.ID = "DynamicControls_" & Me.UserControlCount
Addhandlers(uc)
Me.PlaceHolder1.Controls.Add(uc)
Upd1.Update()
End Sub
Private Sub ucAsyncButton1Clicked(ByVal sender As Object, ByVal e As EventArgs)
'only to demonstrate how to add control dynamically and update the UpdatePanel'
addUserControl()
Me.Upd1.Update()
End Sub
Private Sub ucAsyncButton2Clicked(ByVal sender As Object, ByVal e As EventArgs)
End Sub
Private Sub ucSyncButtonClicked(ByVal sender As Object, ByVal e As EventArgs)
End Sub
Private Sub ucAsyncDropDownSelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
End Sub
ascx which holds your controls:
<%# Control Language="vb" AutoEventWireup="false" CodeBehind="DynamicControls.ascx.vb" Inherits="AJAXEnabledWebApplication1.DynamicControls" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<asp:UpdatePanel ID="myUpdatePanel" runat="server" UpdateMode="Conditional"
ChildrenAsTriggers="false">
<ContentTemplate>
<asp:TextBox ID="textBox1" runat="server" />
<asp:TextBox ID="textBox2" runat="server" />
<asp:Button ID="asyncButton1" runat="server" Text="Button1" />
<asp:DropDownList ID="asyncDropDown" runat="server" AutoPostBack="true" />
<asp:Button ID="asyncButton2" runat="server" Text="Button2" />
<asp:Button ID="syncButton" runat="server" Text="SyncButton" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="asyncButton1" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="asyncButton2" EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="asyncDropDown" EventName="SelectedIndexChanged" />
<asp:PostBackTrigger ControlID="syncButton" />
</Triggers>
</asp:UpdatePanel>
Codebehind of UserControl:
Public Partial Class DynamicControls
Inherits System.Web.UI.UserControl
Public Event asyncButton1Clicked(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event asyncButton2Clicked(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event syncButtonClicked(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event asyncDropDownSelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Private Sub asyncButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles asyncButton1.Click
RaiseEvent asyncButton1Clicked(sender, e)
End Sub
Private Sub asyncButton2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles asyncButton2.Click
RaiseEvent asyncButton2Clicked(sender, e)
End Sub
Private Sub syncButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles syncButton.Click
RaiseEvent syncButtonClicked(sender, e)
End Sub
Private Sub asyncDropDown_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles asyncDropDown.SelectedIndexChanged
RaiseEvent asyncDropDownSelectedIndexChanged(sender, e)
End Sub
End Class
On this way you won't have problems with ClientID's.
Addition:
If you need access to the controls of your UserControls in the event-handlers, use one of following two options:
cast the sender's NamingContainer to the userControl's type: Dim uc As DynamicControls = DirectCast(DirectCast(sender, Control).NamingContainer, DynamicControls)
replace all occurences of (ByVal sender As Object, ByVal e As System.EventArgs) with (uc as DynamicControls). On this way the reference of your UserControl is added to the event as parameter and you could access public properties of it from the page, f.e.:
dim txt1 as String = uc.Text1
If you have exposed a property Text1 in the UserControl:
Public Property Text1() As String
Get
Return textBox1.Text
End Get
Set(ByVal value As String)
textBox1.Text = value
End Set
End Property
The second option is the cleanest and most readable way.
Update:
According to your comment: you should place the UpdateProgress in the UserControl inside of the UpdatePanel that gets updated. Remember to set the AssociatedUpdatePanelID correctly. For example:
<asp:UpdatePanel ID="UdpForm" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false" >
<ContentTemplate>
<asp:panel ID="FormPanel" runat="server">
<asp:UpdateProgress ID="UpdateProgress1" DynamicLayout="true" runat="server" AssociatedUpdatePanelID="UdpForm" DisplayAfter="0" >
<ProgressTemplate>
<div class="progress">
<asp:Image ID="ImgProgress1" runat="server" ImageUrl="~/images/ajax-loader-arrows.gif" ToolTip="loading..." /> please wait...
</div>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:FormView ID="FormView1" runat="server" DefaultMode="ReadOnly" >
<ItemTemplate></ItemTemplate>
<EditItemTemplate></EditItemTemplate>
<InsertItemTemplate></InsertItemTemplate>
<EmptyDataTemplate>
</EmptyDataTemplate>
<PagerTemplate >
</PagerTemplate>
</asp:FormView>
</asp:panel>
</contenttemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpdContent" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false" >
<ContentTemplate>
<asp:Panel ID="PnlMain" runat="server">
<asp:UpdateProgress ID="UpdateProgress2" DynamicLayout="true" runat="server" AssociatedUpdatePanelID="UpdContent" DisplayAfter="0" >
<ProgressTemplate>
<div class="progress">
<asp:Image ID="ImgProgress1" runat="server" ImageUrl="~/images/ajax-loader-arrows.gif" ToolTip="loading..." /> please wait...
</div>
</ProgressTemplate>
</asp:UpdateProgress>
Content
</asp:Panel>
</ContentTemplate>
<Triggers ></Triggers>
</asp:UpdatePanel>

Resources