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

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

Related

TextBox TextChange event is not working in vb.net

I am using asp textbox control with TextChange event, trying to set the text to label as the textbox text get changed but it is working when i loose the focus from textbox not when text changes.
the problem with loosing focus is that if i use AutoPostBack="true" it refresh the page which affects my other values...
my source for textbox on aspx page
<asp:TextBox ID="txtSearchCust" runat="server" Width = "200" OnTextChanged="txtSearchCust_TextChanged" AutoPostBack="true" />
my code behind page source
Protected Sub txtSearchCust_TextChanged(sender As Object, e As EventArgs) Handles txtSearchCust.TextChanged
QtyChk.Text=txtSearchCust.Text
End Sub
here QtyChk is the label where I am trying to set the text
any solution...?
Based on your question.
<script type="text/javascript">
function doTextBoxChange() {
__doPostBack();
}
</script>
<asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" onkeydown="return doTextBoxChange();"></asp:TextBox>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack() Then
LabelChange()
End If
End Sub
Sub LabelChange()
Label1.Text = "1234"
End Sub
But I think use javascript is a better option.
The values will disappear after post, you need to request the value and setup.
otherwise, use viewstate or session.
Using the javascript, don't post form data.
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server" onkeyup="return doTextBoxChange();"></asp:TextBox>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
</div>
</form>
function doTextBoxChange() {
var inputValue = document.getElementById("TextBox1").value;
document.getElementById('<%= Label1.ClientID %>').innerHTML = inputValue;
}

How to dynamically add controls and preserve Viewstate?

I'm attempting to use Controls.AddAt(), but it apparently breaks controls at later indexes:
Here's my minimal example:
Aspx put in a form:
<asp:DropDownList runat="server" ID="ddl" />
<asp:Button Text="text" runat="server" OnClick="Unnamed2_Click" />
Code Behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ddl.Items.Add("Click the button")
'Controls.Add(New HyperLink) 'Works fine, but is put at end of collection.
'Controls.AddAt(2 ,New HyperLink) 'Is also safe but I wanted the control first
Controls.AddAt(0, New HyperLink) 'ddl loses it's item after postback
End If
End Sub
On the first postback of the page after calling AddAt, the DropDownList loses it's item. It doesn't matter what kind of control I add even HTMLControls. Viewstate is not disabled.
How do I dynamically add controls without breaking others?
If you used a PlaceHolder to add your HyperLink into, it would not mess up the rest of the page:
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:DropDownList ID="ddl" EnableViewState="true" runat="server" />
<asp:Button ID="bn1" Text="text" OnClick="Unnamed2_Click" runat="server" />
With code like
Protected Sub Unnamed2_Click(sender As Object, e As EventArgs) Handles bn1.Click
Dim newItem = "Click the button" & DateTime.Now.ToString("HH:mm:ss")
ddl.Items.Add(newItem)
ddl.SelectedIndex = ddl.Items.Count - 1
PlaceHolder1.Controls.Add(New HyperLink With {.ID = "hyp", .Text = "Hyperlink here"})
End Sub
And always give your asp:Controls an ID if they take one.

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.

ModalPopupExtender not displaying on button postback within updatepanel

I know this flavor of question has been asked multiple times, but I've spent hours sifting through answers that don't match or don't work and I'm at wits end.
Background: I have a situation where I want to evaluate a record to make sure it fits a specific set of criteria. If it fits the criteria, raise an alert message for confirmation from the user. I do not want to raise the popup unless the criteria matches.
Pseudocode of what I want to accomplish:
User enters information in multiple fields
User clicks "Save" (cmdUpdate)
within the "Save" click function it checks to see if the same record already exists
in the database (e.g. this is a duplicate).
If it's not a duplicate continue with the save function
If it's a duplicate prompt the user for confirmation to save the dup.
I can't get the popup to display before/after the postback. I've tried a hack workaround of setting a session value to maintain the state. The value tests positive in the prerender and does call the modalpopupextender.show but it never fires successfully to the screen. I'm not opposed to switching to a javascript solution if someone has a better method but I have to do the check for duplicates in the asp.net code behind.
Markup:
<asp:UpdatePanel ID="upMainContent" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="False" >
<ContentTemplate>
<asp:Label ID="lblDummy" runat="server" EnableViewState="false" Style="display: none;" />
<asp:Panel ID="pnlConfirmation" runat="server" Width="400px" Style="display: none;" CssClass="ModalPopupFront">
<div ID="Div1" runat="server" class="PopupHeader" style="width:400px;"> Duplicate Record</div>
<br />
<asp:Label ID="lblConfirmationMessage" runat="server" Text="This record has already exists.<br/> Are you sure you want to save a duplicate entry?"></asp:Label><br />
<br />
<div style="text-align:right;">
<asp:Button ID="btnSaveAnyway" runat="server" Text="Save" OnClick="btnSaveAnyway_Click" />
<asp:Button ID="btnCancelSave" runat="server" Text="Cancel" OnClick="btnCancelSave_Click" />
</div>
</asp:Panel>
<ajax:ModalPopupExtender ID="mpeSaveConfirmation" runat="server" Enabled="False"
TargetControlID="lblDummy" PopupControlID="pnlConfirmation"
BackgroundCssClass="modalBackground" DropShadow="true"
CancelControlID="btnCancelSave"
RepositionMode="RepositionOnWindowResizeAndScroll" PopupDragHandleControlID="pnlConfirmation" Drag="true">
</ajax:ModalPopupExtender>
<!-- all the input fields/misc content -->
<asp:Button id="cmdUpdate" runat="server" CausesValidation="true" OnClick="cmdUpdate_Click" Text="Save" ValidationGroup="vg1" ToolTip="Save the current record" TabIndex="102" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlStateId" EventName="SelectedIndexChanged" />
<asp:AsyncPostBackTrigger ControlID="ddlCountyId" EventName="SelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>
Code behind:
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
'...
If GetSessionValue("HackWorkaround") Then
mpeSaveConfirmation.Enabled = True
mpeSaveConfirmation.Show()
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'...
If not Page.IsPostBack Then
SetSessionValue("HackWorkaround", False)
End if
'...
End Sub
Protected Sub cmdUpdate_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If tbOpTill.NewRecordIdenticalToLast() And tbOpRecord.NewRecordIdenticalToLast() Then
SetSessionValue("HackWorkaround", True)
Else
SetSessionValue("HackWorkaround", False)
SetSessionValue("LastOpRecordIDSaved", tbOpRecord.OpRecordId)
Dim isEdit As Boolean = ResetOpRecord("Till", tbOpTill)
SmartRedirect("Optill/oprecord_edit.aspx")
End If
End Sub
Protected Sub btnSaveAnyway_Click(ByVal sender As Object, ByVal e As System.EventArgs)
SetSessionValue("HackWorkaround", False)
mpeSaveConfirmation.Enabled = False
mpeSaveConfirmation.Hide()
'Duplicate record exists, but the customer wants to save anyway.
DoSave()
Dim isEdit As Boolean = ResetOpRecord("Till", tbOpTill)
SmartRedirect("Optill/oprecord_edit.aspx")
End Sub
Protected Sub btnCancelSave_Click(ByVal sender As Object, ByVal e As System.EventArgs)
SetSessionValue("HackWorkaround", False)
mpeSaveConfirmation.Enabled = False
mpeSaveConfirmation.Hide()
'do nothing and return to the screen.
End Sub
Your issue is here:
<ajax:ModalPopupExtender ID="mpeSaveConfirmation" runat="server" Enabled="False"
Protected Sub btnSaveAnyway_Click(ByVal sender As Object, ByVal e As System.EventArgs)
SetSessionValue("HackWorkaround", False)
**mpeSaveConfirmation.Enabled = False**
mpeSaveConfirmation.Hide()
Make it true in code behind. and sync hide show accordingly. Also i can see in your code at some places you are using Style="display:none". So if you want to display you need use HtmlStyleWriter.Display,"block". If you use Visible true false in that case it will not work. I mean to say, that where ever you are using visible true false, in codebehind you have to use similar. If you are using style, then in codebehind you have to use the same.

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