Random image in UpdateProgress - asp.net

I have a wizard control inside an updatepanel. Some of the wizard steps take a few seconds to display, so I want to show an updateprogress control while they're loading. This is working, but I'd like to show a different image (random image selected from a folder) in the progresstemplate between each wizardstep.
I am able to access the image control and change the ImageUrl, but the progresstemplate never updates. It retains the first random image chosen from the very first time it loads.
I've tried updating the imageUrl on PageLoad and also by overriding the Render() method, but neither works.
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="500" >
<ProgressTemplate>
<div class="modalWrapper">
<div class="updateProgress">
<asp:Image ID="imgLoading" runat="server" AlternateText="Loading..." />
</div>
</div>
</ProgressTemplate>
</asp:UpdateProgress>
In codebehind:
protected void Page_Load(object sender, EventArgs e)
{
System.Web.UI.WebControls.Image img = (System.Web.UI.WebControls.Image)UpdateProgress1.FindControl("imgLoading");
if (img != null)
img.ImageUrl = PickImageFromDirectory("~/images/loaders/"); //returns "~/images/loaders/randomimage.gif"
}
ALSO TRIED:
protected override void Render(HtmlTextWriter writer)
{
System.Web.UI.WebControls.Image img = (System.Web.UI.WebControls.Image)UpdateProgress1.FindControl("imgLoading");
if (img != null)
img.ImageUrl = PickImageFromDirectory("~/images/loaders/"); //returns "~/images/loaders/randomimage.gif"
base.Render(writer);
}

Your image is more than likely not being reloaded because the UpdateProgress sits outside your UpdatePanel. The nature of the UpdatePanel is that only the controls within it are updated on an asynchronous request. =)
Here's what you can do:
Change PickImageFromDirectory to be a static method and mark it as a WebMethod in the code-behind:
[WebMethod]
public static string PickRandomImage()
{
// Logic to return the full path to a random image
}
Then, on the client-side place the following script at the bottom:
<script type="text/javascript">
function requestEnded()
{
PageMethods.PickRandomImage(imageSuccess, imageFailed);
}
function imageSuccess(result,ctx,methodName)
{
document.getElementById('<%= imgLoading.ClientID %>').src = result;
}
function imageFailed(err,ctx,methodName)
{
alert(err);
}
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(requestEnded);
</script>
After every asynchronous postback this will call your server-side web method and set the image src to a random url. =)

You can specify an url than goes to an aspx page :
<asp:Image runat="server" ImageUrl="GenerateImage.aspx"/>
In GenerateImage.aspx :
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "image/jpeg";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Write(GetRandomImageData());
Response.End();
}

Related

ASP.Net NPE inside hidden parent container if not asp control

Going back from JSF to ASP.Net I have a problem in following markup:
I get a null pointer exceptin on this.value within the panel component. I even called DataBind() on the panel itself.
<asp:Panel id="pnl" runat="server" visible="<%# this.value != null%>">
<%= this.value.Foo %>
</asp:Panel>
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
if (this.value == null)
return;
this.pnl.DataBind();
}
Must i use an asp control always?
You probably have mistakes here :
You should do inside : <%# this.value.Foo %>
Capital letter : Visible {capital}).
The code inside the panel will still be executed even if the panel is not visible. It will not be rendered into the result but it will be executed. I would recommend that you use control properties and set your values via code behind on controls that are not repeating anything
<asp:Panel id="pnl" runat="server">
<asp:Literal ID="literal" runat="server" />
</asp:Panel>
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
if(this.value != null)
{
pnl.Visible = true;
literal.Text = this.value.Foo;
}
else
{
pnl.Visible = false;
}
}

Radio button doesn't get selected after a post back

I have an item template within repeater:
<ItemTemplate>
<li>
<input type="radio"
value="<%# GetAssetId((Guid) (Container.DataItem)) %>"
name="AssetId"
<%# SelectAsset((Guid) Container.DataItem) %> />
</li>
</ItemTemplate>
I have a method that compares ids and decides whether to check the radio button.
protected string SelectAsset(Guid uniqueId)
{
if (uniqueId == GetSomeId())
return "checked=\"checked\"";
return string.Empty;
}
SelectAsset gets hit, but it doesn't select a radio button on a post back, but it does work if I just refresh the page. What am I doing wrong here?
Answer here: How to display "selected radio button" after refresh? says that it's not possible to achieve, is this really the case?
Thank you
Update
It appears that view state isn't available for simple controls if they don't have a runat attribute. I have solved this by using a custom GroupRadioButton control. Thank you for your help.
I'd suggest using a RadioButtonList:
Page Code
<asp:RadioButtonList RepeatLayout="UnorderedList" OnSelectedIndexChanged="IndexChanged" AutoPostBack="true" ID="RadioRepeater" runat="server" />
<asp:Label ID="SelectedRadioLabel" runat="server" />
Code Behind
if (!Page.IsPostBack)
{
/* example adds items manually
- you could iterate your datasource here as well */
this.RadioRepeater.Items.Add(new ListItem("Foo"));
this.RadioRepeater.Items.Add(new ListItem("Bar"));
this.RadioRepeater.Items.Add(new ListItem("Baz"));
this.RadioRepeater.SelectedIndex = this.RadioRepeater.Items.IndexOf(new ListItem("Bar"));
this.RadioRepeater.DataBind();
}
protected void IndexChanged(object sender, EventArgs e)
{
this.SelectedRadioLabel.Text = string.Format("Selected Item Text: {0}", this.RadioRepeater.SelectedItem.Text);
}
I assume you only need to select one item.
As described in the comments, it even works to access the SelectedItem in the Page_Loadevent handler:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// previous code omitted
}
else
{
string foo = this.RadioRepeater.SelectedItem.Text;
}
}
If you are creating all your controls dynamically at run-time (directly from code), then things are a little different. Here is the code that I used:
Page Code
<form id="form1" runat="server">
</form>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
RadioButtonList rbl = new RadioButtonList();
rbl.AutoPostBack = true;
rbl.SelectedIndexChanged += rbl_SelectedIndexChanged;
rbl.Items.Add("All");
// generate your dynamic radio buttons here
for (int i = 0; i<5; i++)
{
rbl.Items.Add(string.Format("Dynamic{0}", i));
}
form1.Controls.Add(rbl);
if (!Page.IsPostBack)
{
rbl.SelectedValue = "All";
PopulateTextBox(rbl.SelectedValue);
}
}
void rbl_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList foo = (RadioButtonList)sender;
PopulateTextBox(foo.SelectedValue);
}
void PopulateTextBox(string selection)
{
TextBox box = new TextBox();
box.Text = selection;
form1.Controls.Add(box);
}

Handling events from dynamic controls NOT added on Page_Load?

I've read a few articles on here and the web that have informed me that I cannot simply add a new control dynamically to the page, wire it to a handler, and expect it to work.
The solution given each time is that the dynamic controls need to be added to the page on Init each time.
My problem is, my controls are NOT added to the page on init, they are added after ANOTHER postback.
the workflow is this:
Page Loads
User fills in a textbox, clicks a button
Page Posts back, creating dynamic link controls in the button_click event based on the input
User clicks one of those link controls to proceed to the next step.
so if this is the behavior I need to support, is there any way to do this? It has to happen in the button_click of step 2, because the dynamic controls are based on the input the user puts in step 2.
have I painted myself into a corner here? how else could I handle such a workflow?
After you dynamically create a link button, set a flag in your page's view state. On postback, re-create the link button if the flag is set in view state. Here's a demo:
Markup:
<asp:Button runat="server" ID="button1" OnClick="button_Click" Text="Create button A" CommandArgument="A" />
<asp:Button runat="server" ID="button2" OnClick="button_Click" Text="Create button B" CommandArgument="B" />
<asp:PlaceHolder runat="server" ID="placeHolder"></asp:PlaceHolder>
Code-behind:
public partial class Default : System.Web.UI.Page
{
private bool LinkButtonCreated
{
get { return ((bool?)this.ViewState["LinkButtonCreated"]).GetValueOrDefault(); }
set { this.ViewState["LinkButtonCreated"] = value; }
}
private string LinkButtonCommandArgument
{
get { return (string)this.ViewState["LinkButtonCommandArgument"]; }
set { this.ViewState["LinkButtonCommandArgument"] = value; }
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (this.LinkButtonCreated)
this.CreateLinkButton(this.LinkButtonCommandArgument);
}
protected void button_Click(object sender, EventArgs e)
{
if (!this.LinkButtonCreated)
{
string commandArgument = ((Button)sender).CommandArgument;
this.LinkButtonCreated = true;
this.LinkButtonCommandArgument = commandArgument;
this.CreateLinkButton(commandArgument);
}
}
private void CreateLinkButton(string commandArgument)
{
LinkButton linkButton =
new LinkButton
{
ID = "linkButton",
Text = "Click me",
CommandArgument = commandArgument,
};
linkButton.Click += this.linkButton_Click;
this.placeHolder.Controls.Add(linkButton);
}
private void linkButton_Click(object sender, EventArgs e)
{
LinkButton linkButton = (LinkButton)sender;
linkButton.Text = "I was clicked! Argument: " + linkButton.CommandArgument;
}
}

Can't get 'Text' property with asp-control

How do I get properties (e.g. Text) with asp.net controls that were created programatically when page loading when IsPostBack parameter is true?
Schema:
creating control (e.g. TextBox box = new TextBox(); box.ID = "BoxID")
display control in page (e.g. SomeControlInPageID.Controls.Add(box))
user see this textbox (with id "BoxID", but we don't have a possibility to get text property use BoxID.Text, because it control was created programatically!) in page & puts in it some text
user click in button (asp:Button) in page and start page reloading process
start Page_Load method & IsPostBack parameter takes the true value
i try to use this code to get Text property in Page_Load method, but it's not work...:
void Page_Load()
{
if (Page.IsPostBack)
{
TextBox box = SomeControlInPageID.FindControl("BoxID") as TextBox;
string result = box.Text;
}
else
{
// creating controls programatically and display them in page
...
}
}
box.Text in this code always takes null value.
The key here is you need to make sure you recreate the dynamic controls each time the page is loaded. Once the controls are created, ASP.NET will be able to fill the posted back values into those controls. I've included a full working example below. Notice I add the control in the OnInit event (which will fire before Page_Load), and then I can read the value back out in the Page_Load event if a postback has occurred.
<%# Page Language="C#" AutoEventWireup="true" %>
<html>
<body>
<form id="form1" runat="server">
<asp:Panel ID="myPanel" runat="server" />
<asp:Button ID="btnSubmit" Text="Submit" runat="server" />
<br />
Text is: <asp:Literal ID="litText" runat="server" />
</form>
</body>
</html>
<script runat="server">
protected void Page_Load(object sender, System.EventArgs e)
{
if(Page.IsPostBack)
{
var myTextbox = myPanel.FindControl("myTextbox") as TextBox;
litText.Text = myTextbox == null ? "(null)" : myTextbox.Text;
}
}
protected override void OnInit(EventArgs e)
{
AddDynamicControl();
base.OnInit(e);
}
private void AddDynamicControl()
{
var myTextbox = new TextBox();
myTextbox.ID = "myTextbox";
myPanel.Controls.Add(myTextbox);
}
</script>
Please have a look into pageLifeCycle of an aspx page. You'll have to add the textbox within the Page_Init handler. Afterwards you may access your textBox in page_load event.
protected void Page_Init(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.ID = "textbox1";
tb.AutoPostBack = true;
form1.Controls.Add(tb);
}
protected void Page_Load(object sender, EventArgs e)
{
/// in case there are no other elements on your page
TextBox tb = (TextBox)form1.Controls[1];
/// or you iterate through all Controls and search for a textbox with the ID 'textbox1'
if (Page.IsPostBack)
{
Debug.WriteLine(tb.Text); /// only for test purpose (System.Diagnostics needed)
}
}
hth

ASP.NET how to access public properties?

I have two pages page1.aspx and page2.aspx, both have code behind with partial classes.
How do i access public property message on page1.aspx from page2.aspx ?
public string message { get; set; }
Update
I just read that the one is MasterPage and the other is the client to masterpage ?
then its diferent way.
Page to Page
If you have 2 simple diferent pages.
I have done it this way.
Its a post value, by using asp.net tricks :)
On Page2.aspx add this on top.
<%# PreviousPageType VirtualPath="Page1.aspx" %>
and how I read from Page1.aspx on code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Page.PreviousPage != null)
{
if(Page.PreviousPage.IsCrossPagePostBack == true)
{
txtGetItFromPreviusPage.Text = PreviousPage.SomeString;
}
}
}
}
On Page1.aspx
the button that send me to Page2.aspx
<asp:Button ID="btnEna" runat="server" Text="Send Some variables to other page"
PostBackUrl="Page2.aspx"
onclick="btnMoveSelection_Click" />
and the code that I use for Page1 calculations or other thinks
public string SomeString
{
set
{
ViewState["txtSomeString"] = value;
}
get
{
if (ViewState["txtSomeString"] != null)
return ViewState["txtSomeString"].ToString();
else
return string.Empty;
}
}
protected void btnMoveSelection_Click(object sender, EventArgs e)
{
// some final calculations
}
If the one is the Master page, and the other is the page that use the master.
The Master Page
<body>
<form id="form1" runat="server">
<div>
<asp:Literal runat="server" ID="txtOnMaster"></asp:Literal>
<br />
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
and the code behind
public partial class Dokimes_StackOverFlow_MasterPage : System.Web.UI.MasterPage
{
public string TextToMaster
{
get { return txtOnMaster.Text; }
set { txtOnMaster.Text = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
// here I find the control in the client page
Control FindMe = ContentPlaceHolder1.FindControl("txtOut");
// and if exist I set the text to client from the master
if (FindMe != null)
{
((Literal)FindMe).Text = "Get from Master Page";
}
}
}
and now the Page1.aspx that have the previus master page
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Literal runat="server" ID="txtOut"></asp:Literal>
</asp:Content>
and the code
protected void Page_Load(object sender, EventArgs e)
{
// here I set the text on master page from client
((Dokimes_StackOverFlow_MasterPage)Master).TextToMaster = "Set from Client";
}
If you are NOT in a sessionless environment, then in the transmitter page, push your string (or your object - e.g., a Dictionary ) into session:
Session("MyVar") = "WhatEver"
In the receiver page, you can get it back with:
MyPreviousVar = Session("MyVar")
If you want a message property on every page. You could implement your own BasePage and define the message property in your base page. Then derive subsequent pages from your custom base page. That way all of your pages will always have a message property.
However, this isn't going to keep the message property constant through out each page. If you are trying to pass values between pages then you should use either session state or a querystring
This MSDN page may be of use to you.
You shouldn't really be doing this, pages should be standalone entities. If you need to pass this data from one form to another, consider using the querystring, or posting your form to the second page.
OK. Have you tried then Page.Master.Property?

Resources