ASP Showing/Hiding a Table during an Event - asp.net

I have a table that has a loading gif inside of it, that starts with the visible property set to false. I also have a drop down list that has a selection change event that will update information on the page depending on what the user selects. What I want to happen is the loading table to become visible at the beginning of the selection change event, the processing of new information with the selection made by the user to occur, then the loading table to go back to being invisible.
Here is what some of my code looks like:
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<table id="tblLoading" runat="server" align="center" width="100%" visible="false">
<tr>
<td align="center">
<img src="../images/Loading_Gif.gif" class="auto-style1" alt="Load" />
</td>
</tr>
<tr align="center">
<td>
<asp:Label runat="server" Font-Names="Tahoma" Font-Size="Larger" Font-Bold="True">Loading...</asp:Label>
</td>
</tr>
</table>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlPayrollPeriodReport" EventName="SelectedIndexChanged"/>
</Triggers>
</asp:UpdatePanel>
<asp:DropDownList ID="ddlPayrollPeriodReport" runat="server" AutoPostBack="True" Font-Size="Large" Font-Names="Tahoma"></asp:DropDownList>
Private Sub ddlPayPeriodReport_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlPayrollPeriodReport.SelectedIndexChanged
'set up the link to the HR system
Me.tblLoading.Visible = True
Dim datStart As Date = CDate(Me.ddlPayrollPeriodReport.SelectedItem.Value)
SetUptblReport(datStart)
Me.tblLoading.Visible = False
End Sub
I found out that I need to place the loading table in an UpdatePanel in order for it to change the value of the visible property. However, I noticed that the table will become visible if I don't have the call that turns it invisible. If I have both calls, then both calls are ignored. I am still new to ASP, so is there something I need to know in order to get this to work the way I want it to work?

The changes made in code-behind become visible only after the postback has completed and the page (or the UpdatePanel) has been refreshed. In your case, the page will show the last change that you made to tblLoading in the SelectedIndexChanged event handler, which is to set visible="False". In other words, it was not visible before the postback, and it is still not visible after it.
To show the loading message, you must make the table visible in client code, before the postback is triggered. In order to do that, the table has to be present in the page. The visible="false" setting does not work well for that because it causes ASP.NET to remove the control from the HTML ouptut. You can hide the table with the display: none style property:
<table id="tblLoading" runat="server" align="center" width="100%" style="display: none;">
To make the table visible before the postback, you can process the DropDownList selection change on the client side:
<asp:DropDownList ID="ddlPayrollPeriodReport" ... onchange="showLoadingMessage();">
The Javascript function could be defined as follows:
<script type="text/javascript">
function showLoadingMessage() {
document.getElementById('<%= tblLoading.ClientID %>').style.display = '';
}
</script>
Note: the <% ... %> syntax ensures that any modification to the ID of the control made by ASP.NET is taken into account.
Finally, you can hide the table in your event handler on the server side:
Private Sub ddlPayPeriodReport_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlPayrollPeriodReport.SelectedIndexChanged
...
tblLoading.Style("display") = "none"
End Sub

Related

Dropdown in listview SelectedIndexChanged doesn't work first time but does after

I've searched high and low, I can't seem to find out what's happening with this. I've simplified the code, but I really have taken it back to as basic as this and still have the same problem.
I have a drop down list in a a repeater (in a Web Form with master page):
<asp:DropDownList ID="TicketQuantityDDL" runat="server" CssClass="qtyddl" AutoPostBack="true" OnSelectedIndexChanged="TicketQuantityDDL_SelectedIndexChanged" CausesValidation="false" SelectedIndex='<%# CInt(Eval("Quantity")) - 1%>'>
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
<asp:ListItem Value="3">3</asp:ListItem>
<asp:ListItem Value="4">4</asp:ListItem>
<asp:ListItem Value="5">5</asp:ListItem>
<asp:ListItem Value="6">6</asp:ListItem>
</asp:DropDownList>
Handler
Protected Sub TicketQuantityDDL_SelectedIndexChanged(sender As Object, e As EventArgs)
myLiteral.text = "Selected Index Changed handled..."
End Sub
The first time the page is loaded if I change the DDL the the page is posted back - the selected index change handler is NOT fired (I've stepped through the code, page.ispostback is true). Every time after the handler works unless the page is full reloaded.
Things I've tried:
Manually adding a handler OnItemCreated
Manually adding a handler OnItemDataBound
Manually registering the control for async postback with scriptmanager
Using OnClientSelectedIndexChanged to trigger postback from the client
Removing AutoPostBack and all of the above again...
I've used Page.Request.Params("__EVENTTARGET") to verify that when the partial postback is fired that the control is the drop down.
Even though viewstate is enabled I've tried specifying this for the control and the page directly.
Disabling validation.
I've tried not binding the value of the drop down and just leaving it
as is with no selected value and then manually setting the initial
selected value - no dice.
Tried removing update panel, same issue.
Things that are DEFINITELY not happening here.
I'm not rebinding on post back if not page.ispostback... databind...
I'm not selecting the same value/first item in the drop down
This isn't an auto ID problem, the controls ID stay the same through postbacks.
I'm not doing anything funky other than binding the repeater to a list of objects.
Why isn't the handler firing the first time? After the first time everything works exactly as intended.
Update
I've replicated the exact same behaviour in a list view. Due to time constraints I've used another approach but I'd really like to know how to fix this or at least know why it doesn't work.
Update 2
I've tested the functionality with a bog standard web form and it functions correctly. Something is up with this being in a contentplaceholder from a masterpage, the script manager or update panel. It's as if the event handler for the dropdown is only registered after the first post back, I've tried registering the handler in DataBound and also in the page LoadComplete events, the same thing still happens.
Update 3
I've since changed it to a list view, I'm having the exact same issue though.
This is on a web form with master page, the master page contains the script manager, the list view is in an update panel, although I've tried removing this and I still have the same issue. I've not included the onselectedindexchanged code, I've made it as simple as changing the text of a literal - doesn't work first post back, does the second.
I had originally specified the list items manually but have changed this to programatically at itemDataBound, still no difference.
As I stated above when I check which control caused the postback it's definitely the ddl, it just doesn't fire selectindexchanged the first time. I've also tried specifying the OnSelectedIndexChange in the control itself, still no dice.
Page load ,bind, list view and on item created code.
Page Load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim _Basket = SessionHandler.getSessionObject(SessionHandler.SessionObjects.Basket)
If _Basket Is Nothing OrElse DirectCast(_Basket, BasketContainer).BasketItemList.Count = 0 Then
BasketSectionContainer.Visible = False
alertLiteral.Text = AlertGenerator.GetAlertHTML("No Items in Basket", "There are no items in your basket, please use the menu above to navigate the site.", AlertGenerator.AlertType.warning)
If _Basket IsNot Nothing Then SessionHandler.removeSessionObject(SessionHandler.SessionObjects.Basket)
Exit Sub
Else
Dim lBasket = DirectCast(_Basket, BasketContainer)
BindBasket(lBasket)
End If
End If
End Sub
Bind
Private Sub BindBasket(lBasket As BasketContainer)
basketListView.DataSource = lBasket.BasketItems
basketListView.DataBind()
bindTotals(lBasket) 'This just sets text of literals on the page outside of the listview
If lBasket.Postage Then
PostageDDL.visible = True 'This is outside of the list view also
End If
End Sub
Item Created
Private Sub basketListView_ItemCreated(sender As Object, e As ListViewItemEventArgs) Handles basketListView.ItemCreated
Dim QtyDDL As DropDownList = DirectCast(e.Item.FindControl("TicketQuantityDDL"), DropDownList)
AddHandler QtyDDL.SelectedIndexChanged, AddressOf TicketQuantityDDL_SelectedIndexChanged
End Sub
_Item Data Bound _
Private Sub basketListView_ItemDataBound(sender As Object, e As ListViewItemEventArgs) Handles basketListView.ItemDataBound
Dim data As BasketItem = DirectCast(e.Item.DataItem, BasketItem)
Dim QtyDDL As DropDownList = DirectCast(e.Item.FindControl("TicketQuantityDDL"), DropDownList)
For i As Integer = 1 To 6
QtyDDL.Items.Add(New ListItem(i.ToString, i.ToString))
Next
QtyDDL.DataTextField = data.BasketItemID.ToString 'no command arg for DDL so using this, I've tested without, doesn't make a difference.
Select Case data.BasketType
Case BasketInfo.BasketItemType.DiscountedTickets, BasketInfo.BasketItemType.Tickets, BasketInfo.BasketItemType.Goods
'tickets and goods...
QtyDDL.Items.FindByValue(data.Quantity.ToString).Selected = True
Case Else
'non ticket or goods type, disable quantity selection
QtyDDL.Items.FindByValue("1").Selected = True
QtyDDL.Enabled = False
End Select
End Sub
_List View _
<asp:ListView ID="basketListView" runat="server">
<LayoutTemplate>
<table class="cart-table responsive-table">
<tr>
<th>Item</th>
<th>Description</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<th></th>
</tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</table>
<table class="cart-table bottom">
<tr>
<th>
<asp:Button ID="ApplyDiscountCodeButton" runat="server" CssClass="button color pull-right" Text="Apply Code" />
<asp:TextBox ID="DiscountCodeTextBox" runat="server" CssClass="discount-tb pull-right" />
</th>
</tr>
</table>
<div class="clearfix"></div>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<img src="/images/shows/<%# Eval("imageURL")%>.jpg" alt="<%#Eval("BasketItemTitle")%>" class="basketimg" /></td>
<td class="cart-title">
<%#Eval("BasketItemTitle")%>
<br />
<%# String.Format("{0:dddd} {1} {0:MMMM yyyy} | {0:HH:mm}", Eval("PerformanceStarts"), Eval("OrdinalDay"))%>
<br />
<%# Eval("VenueTitle")%>
</td>
<td>
<%#Eval("PriceBandType")%>
<br />
# <%# String.Format("{0:c}", Eval("PriceBandValue"))%>
</td>
<td>
<asp:DropDownList ID="TicketQuantityDDL" runat="server" CssClass="qtyddl" AutoPostBack="true" ClientIDMode="Static" />
</td>
<td class="cart-total"><%#String.Format("{0:c}", Eval("BasketItemTotalValue"))%></td>
<td>
<asp:LinkButton ID="RemoveLinkBtn" runat="server" CssClass="cart-remove" CommandName="RemoveBasketItem" CommandArgument='<%#Eval("BasketItemID")%>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Since the Dropdown in inside the repeater, you can try the following Option instead.
Add OnItemCommand to the repeater. This should definitely Trigger the Event on selection Change in the Dropdown. Then in the OnItemCommand you Need to cast the Sender to DropDownList to be able get the selected value of the dropdown
You have to register the dropdown list event like this.
protected virtual void OnRepeaterItemCreated(object sender, RepeaterItemEventArgs e)
{
DropDownList dropdown = (DropDownList)e.Item.FindControl("TicketQuantityDDL");
dropdown.SelectedIndexChanged += TicketQuantityDDL_SelectedIndexChanged;
}
And also add this piece of code in your repeater.
OnItemCreated="OnRepeaterItemCreated"
And then you can do the selected index changed event like this.
protected void TicketQuantityDDL_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList mydropdownlist = (DropDownList)sender;
Response.Write(mydropdownlist.SelectedValue);
}
protected void dropdownlist1_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddlListFind = (DropDownList)sender;
ListViewItem item1 = (ListViewItem)ddlListFind.NamingContainer;
DropDownList getDDLList = (DropDownList)item1.FindControl("dropdownlist1");
Label lblMessage = (Label)item1.FindControl("lblMsg");
lblMessage.Visible = true; lblMessage.Text = "dropDown text is : " + getDDLList.SelectedItem.Text + " and value is : " + getDDLList.SelectedItem.Value;
}

Hiding a table row (the ItemPlaceholderID row) in a ListView

I have a table row that holds my paging controls in a ListView as follows (partial layout):
<asp:ListView ID="lvOrderItems" runat="server"
DataSourceID="odsShoppingCart"
DataKeyNames="ProductNumber"
ItemPlaceholderID="lvItemContainer">
<LayoutTemplate>
<table id="lvCart" runat="server">
<tr id="lvHeader" runat="server">
...
</tr>
<tr id="lvItemContainer" runat="server"></tr>
<tr id="lvPaging" runat="server">
...
</tr>
</table>
</LayoutTemplate>
In my code-behind, I handle the DataBound event as follows, and I am planning on hiding the entire lvItemContainer row conditionally (for now, I am just trying to hide the row itself without conditions):
Protected Sub lvOrderItems_DataBound(ByVal sender As Object, ByVal e As EventArgs) Handles lvOrderItems.DataBound
Dim lvItemContainer As HtmlTableRow = CType(lvOrderItems.FindControl("lvItemContainer"), HtmlTableRow)
If Not lvItemContainer Is Nothing Then
Response.Write("hit1")
lvItemContainer.Visible = False
End If
Dim lvPaging As HtmlTableRow = CType(lvOrderItems.FindControl("lvPaging"), HtmlTableRow)
If Not lvPaging Is Nothing Then
Response.Write("hit2")
lvPaging.Visible = False
End If
End Sub
So when this runs on DataBound, hit1 is never fired, but hit2 is... any ideas what is happening here?
HTML purists don't like it, but this approach works:
In the OnLayoutCreated event, try one of the following approaches:
Take the runat="server" out of the table and child rows, and do this:
<asp:Panel ID="pnlItemContainer" runat="server">
<tr id="lvItemContainer"></tr>
</asp:Panel>
pnlItemContainer.Visible = false;
Or you can do this:
<tr id="lvItemContainer" runat="server"></tr>
EDIT: Embedded style element because setting visible to false does not work in the layout template.
lvItemContainer.Style["display"] = "none";
I'm not sure how it will work with a layout template, but it's worked for me in other situations.
Instead of attempting to (unsuccessfully) adjust the visibility of the ItemPlaceholderID container, I've set the visibility of the individual rows in the container.

UpdatePanel async postback not updating content

I have an issue very similar to this question. There is a dropdown on my page that causes a postback, during which the ImageUrl property of an ASP:Image is changed. When that postback happens, any value that is in the FileUpload is cleared. That's the problem I'm trying to solve, but I ran into this issue in the process.
I'm trying to solve the problem by wrapping the dropdown and image in an UpdatePanel. Here is my ASP markup:
<asp:UpdatePanel ID="upPanel" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="myDropdown"
EventName="SelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<tr valign="top">
<td>Tag:</td>
<td>
<asp:DropDownList ID="myDropdown" runat="server"
AppendDataBoundItems="true" DataTextField="Name"
DataValueField="ID" AutoPostBack="true">
<asp:ListItem Value="" />
</asp:DropDownList>
</td>
</tr>
<TR vAlign="top">
<TD width="150">Thumbnail:</TD>
<TD>
<asp:Image id="imgThumbnail" Runat="server"
AlternateText="No Image Found"
Visible="false"></asp:Image><BR>
</TD>
</TR>
</ContentTemplate>
</asp:UpdatePanel>
EDIT: my code-behind doing the update is here:
Private Sub myDropdown_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles myDropdown.SelectedIndexChanged
If (myDropdown.SelectedValue <> "-1") Then
imgThumbnail.ImageUrl = Application("AppPath") + "/Modules/Broadcaster/ImageGen.ashx?tag=" + myDropdown.SelectedValue
Else
imgThumbnail.ImageUrl = Application("AppPath") + "/Modules/Broadcaster/ImageGen.ashx?defaultTag=" + _modID.ToString()
End If
End Sub
I can see the async postback happening in FireBug, but the image URL does not change. What am I doing wrong?
You're missing the code that's doing the update (the code that is called by the selected index changing within the dropdown); however, I'm going to venture a guess that your problem is being caused because you are loading the DDL through a control instead of programmatically.
The reason you may be running into this issue is because the page load function is called before the datasource controls are populated, which means that the DDL is not populated by the time you are looking for a value, thus your image is coming up with a blank.
Example:
Dim sTemp As String = "images/myimagenumber" & myDropdown.SelectedIndex & ".jpg"
This will return "images/myimagenumber.jpg" as the value of the sTemp string because there is no value or index selected the the moment the page loads.
I suggest you load the values of the dropdownlist manually (programmatically) and then in the page_load subroutine make sure that it's only repopulating the dropdown when the page loads for the first time.
VB.Net Example:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
If Page.IsPostback = False Then
runDBLFillSubHere()
End If
'Run Rest of Code Here'
Sub
I've run into this a couple times over the years and it always ends up being because the DDL isn't populated before I am accessing it.

Default radio button not triggering an UpdateControl postback

I have three radio buttons on a form - A, B, C. Each of these selections populates a dropdown list with data specific to the option. When the form loads, I set option A to be checked (as the default).
When I select buttons B or C, the AsyncPostBack triggers fine and the dropdown is populated. BUT, subsequently selecting A from either B or C does not trigger the event.
I suspect that because A was checked when the form loaded, the browser is not seeing any "change" to raise the event.
So what can be done to enable the default A button recognise it is being changed from B or C in order to raise the postback?
I have tried both setting the checked state of button A in code on inital loading of the page only (ie IsPostBack is False) and alternatively setting the checked attribute of the radiobutton in the html, with the same results. If I don't default the radio button the functionality works as expected, except I don't have the radio button and dropdown list defaulted when the page first loads.
The html...
<asp:RadioButton ID="radBook" runat="server" AutoPostBack="true" GroupName="grpArticleType" Text="Book" />
<asp:RadioButton ID="radCD" runat="server" AutoPostBack="true" GroupName="grpArticleType" Text="CD" />
<asp:RadioButton ID="radDVD" runat="server" AutoPostBack="true" GroupName="grpArticleType" Text="DVD" />
<asp:UpdatePanel ID="pnlTasks" runat="server" UpdateMode="Conditional" RenderMode="Inline">
<ContentTemplate>
<asp:DropDownList ID="dropShippingSize" runat="server" CssClass="dropdownMandatory"></asp:DropDownList>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="radBook" />
<asp:AsyncPostBackTrigger ControlID="radCD" />
<asp:AsyncPostBackTrigger ControlID="radDVD" />
</Triggers>
</asp:UpdatePanel>
The code behind...
Sub Page_Load
If Not Me.IsPostBack Then
radBook.Checked = True
End If
End Sub
Private Sub rad_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles radBook.CheckedChanged, radCD.CheckedChanged, radDVD.CheckedChanged
zLoadShippingSizeDropdown()
End Sub
I had the same problem and looked for an answer for hours. This seems to have nothing to do with ViewState or anything similar, but with some kind of incompatibility of using a pre-checked RadioButton as trigger for an Async PostBack.
The work around I found is amazingly easy and worked right away; instead of using the checked=true on the mark-up or myRadioButton.Checked on the server side, I did the following:
Not setting the attribute on Mark-up and add this on the Page_Load event:
if (!IsPostBack)
{
MyRadioButton.InputAttributes["checked"] = "true";
...
}
I hope this helps and saves some people hours of hair pulling :)
I'm guessing you need to need to check if the page is a postback in your load event:
protected void Form_Load(object sender, EventArgs e)
{
if (!Page.IsPostback)
{
// Set radiobutton A...
}
}
We had the same problem and it seems you will have to set the other "checked" property for radio buttons to "false".
So please add the lines
radCD.Checked = False
radDVD.Checked = False
Are you by chance handling viewstate in your code behind as well? If so then you need to handle the AJAX version of it as viewstate can often be lost on AJAX style pages. Try putting your buttons inside the update panel and see if you get the same behaviour if the panel has it's update mode set to conditional. Don't worry about the postback triggers if you do that.
The asynch triggers are only for items inside an update panel. any item outside of a panel will doa full postback by design.
<asp:UpdatePanel ID="pnlTasks" runat="server" UpdateMode="Conditional" RenderMode="Inline">
<ContentTemplate>
<asp:RadioButton ID="radBook" runat="server" AutoPostBack="true" GroupName="grpArticleType" Text="Book" />
<asp:RadioButton ID="radCD" runat="server" AutoPostBack="true" GroupName="grpArticleType" Text="CD" /><asp:RadioButton ID="radDVD" runat="server" AutoPostBack="true" GroupName="grpArticleType" Text="DVD" />
<asp:DropDownList ID="dropShippingSize" runat="server" CssClass="dropdownMandatory">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
WOW, I would have never thought that could be the bug. Saved many hours of frustration.
Thanks Juan going through the carppy Microsoft issue and found a solution for the rest.

Ajax callback UpdatePanel.Update() still reloading whole page

I have code in an Update Panel and even though on a button click i am inserting data into a db and simply calling Updatepanel.Update() the whole page is reloaded:
Gifts.ASPX
<table style="width:100%;">
<tr>
<td>
<asp:Label ID="Label2" runat="server" Text="Gift"></asp:Label>
</td>
<td>
<asp:UpdatePanel ID="UpdatePanel3" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="txtNewGift" runat="server"></asp:TextBox>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
<tr>
Gifts.aspx.CS
protected void cmdAddGift_Click(object sender, EventArgs e)
{
OleDbConnection objConn = new OleDbConnection(DataSource);
Random r = new Random();
int giftID = r.Next(1200, 14000);
OleDbCommand objCommand = new OleDbCommand("Insert into Gifts (GiftID, Description) values (" + giftID + ",'" + txtNewGift.Text + "')", objConn);
ExecuteCommand(objCommand);
PopulateGifts(objConn);
txtNewGift.Text = "";
UpdatePanel3.Update();
}
Any ideas why this whole page would reload instead of just the textbox getting update?
Where is the button in the above example? Inside or outside the UpdatePanel. If it is outside you will need to add it to the triggers collection of the UpdatePanel.
Also you only need to call UpdatePanel.Update() if you are changing the content of an UpdatePanel other than the one that caused the (Partial) postback.
As a side note (and personal crusade), it is recommended that a using statement is put around your DB connection.
With the markup below, the following will happen:
btnInnerPart is inside the update panel, so it will automatically cause a partial postback
btnInnerFull will cause a full postback as it has a PostBackTrigger in the trigger collection
btnOuterPart will cause a partial postback as it has an AsyncPostBackTrigger in the trigger collection
btnOuterFull will cause a full postback as it is outside the UpdatePanel
Markup:
<asp:UpdatePanel runat="server">
<ContentTemplate>
<!-- Content -->
<asp:Button runat="server" ID="btnInnerPart" Text="Inner Part" />
<asp:Button runat="server" ID="btnInnerFull" Text="Inner Full" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnOuterPart" />
<asp:PostBackTrigger ControlID="btnInnerFull" />
</Triggers>
</asp:UpdatePanel>
<asp:Button runat="server" ID="btnOuterFull" Text="Outer Full" />
<asp:Button runat="server" ID="btnOuterPart" Text="Outer Part" />
Where is the button on Gifts.ASPX? If you put the button inside the UpdatePanel or use triggers you don't need to call UpdatePanel3.Update(); from the code behind.
Also, You need to have a ScriptManager object on your page. Do you have one?
please check tag of update panel...you have to specify the trigger controls for update panel on on which the update panel will get update

Resources