Avatar of Siv
Siv
Flag for United Kingdom of Great Britain and Northern Ireland asked on

ASP.NET - How to flash the background of text boxes after saving to indicate something happened.

I am working on an asp.net project using c# as the language used and want to emulate what I have always done in desktop applications which is when a user saves a record and the save is successful, I clear the text boxes of input, flash the background colour of the cleaned boxes to a non-white (usually use Powder Blue or a similar pale colour) and then reload the saved data to show that the information has been stored successfully. Then return the BackColor to white again.

With web pages I would like to do the same thing but without generating masses of web traffic, so maybe there is a neat way of doing  that?  

At the moment I am saving the record then calling my PopulateScreen routine that does a call to my ClearScreen routine and then populates the text boxes from the database again.  My ClearScreen routine looks like this:

      private void ClearScreen()
      {
            try
            {
                  txtEmailAddress.BackColor = System.Drawing.Color.PowderBlue;
                  txtFirstName.BackColor = System.Drawing.Color.PowderBlue;
                  txtSurname.BackColor = System.Drawing.Color.PowderBlue;
                  cboUserType.BackColor = System.Drawing.Color.PowderBlue;
                  txtPassword.BackColor = System.Drawing.Color.PowderBlue;

                  txtEmailAddress.Text = "";
                  txtFirstName.Text = "";
                  txtSurname.Text  = "";
                  cboUserType.SelectedValue = "0"; //First entry in list
                  txtPassword.Text = "";

                  System.Threading.Thread.Sleep(500);

                  txtEmailAddress.BackColor = System.Drawing.Color.White;
                  txtFirstName.BackColor = System.Drawing.Color.White;
                  txtSurname.BackColor = System.Drawing.Color.White;
                  cboUserType.BackColor = System.Drawing.Color.White;
                  txtPassword.BackColor = System.Drawing.Color.White;

            }
            catch(Exception ex)
            {
                  Common.PEH("PopulateScreen", "frm4-02", ex.Message);
            }
      }

When I run this I don't see the BackColor change it's as if the half second delay doesn't do anything, as I don't see the BackColor go blue and I am concerned that using Thread.Sleep is probably a ham fisted way of doing it.

I have found ways of throwing up an alert box confirming that the record is saved,  but I'd rather not force the user to have to click the dialog every time they save.

Any help with this appreciated.

Siv
ASP.NET.NET ProgrammingC#

Avatar of undefined
Last Comment
Siv

8/22/2022 - Mon
kaufmed

You need to get a firm understanding of the client/server paradigm of web programming. Code that runs on the server does just that:  runs on the server. You client cannot see what goes on on the server. It only sees the response that the server generates for it, which is typically just HTML. You cannot code with the same mentality that you used in desktop applications (even though Web Forms does its best to allow you to that).

What you will have to do is employ Javascript code (or possibly CSS3 transitions) that manipulates your elements on the page. This all happens client-side; your C# won't have anything to do with this. You can use the JQuery library to help ease some of the code writing if you go the Javasript route.
Siv

ASKER
Any pointers as to which JQuery stuff might be of use. I have not used JQuery yet so it's a bit of a minefield.
kaufmed

Here is one example:

https://jadendreamer.wordpress.com/2013/01/11/jquery-tutorial-blinking-elements-continously-or-a-specific-number-of-times/

It's got a bit more than just one element in it, but you can go to the linked JSFiddle and play around with individual elements:

e.g.

http://jsfiddle.net/Nx4qS/1461/
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Siv

ASKER
I have read through the JQuery stuff and think I understand the concept, the question would be how would I fire that from the ASP.NET code when I save the record? In the example it just seems to run
kaufmed

How do you save your records? Is this a full post back to the server (i.e. the whole page), or are you using AJAX to submit your form?
Siv

ASKER
On the input form I have a button which when clicked calls a class module that maps to the table used in the database. In that class I have Add Amend Delete functions.

These  routines use OleDB to write to an Access database table. Once the class module returns true to indicate that the database has successfully updated, I clear the text boxes, I then call my GetRecord function in the Class module that maps to the underlying table. The data is then written back to the screen to demonstrate that the data has been updated.

At the moment the screen doesn't appear to change as it's too quick or like you say because the things I want to appear in the client screen are happening on the server and not being replayed on the web page,

Siv
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
kaufmed

Sorry, what I mean is, when you push the button, does the entire page refresh, or does only part of the page refresh?
Siv

ASKER
I think the page gets reloaded when anything happens in the code behind. I am not calling any JavaScript to make stuff happen other than making an alert show to confirm the record is saved and that's what I'd like to get rid of. Here are all the C# code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.OleDb;

public partial class frm4_02 : System.Web.UI.Page
{
	public int ExchAccID = 0;

	protected void Page_Load(object sender, EventArgs e)
	{
		
			if(Request.QueryString["ID"] != null)
			{
				ExchAccID = Convert.ToInt32(Request.QueryString["ID"]);

				if(!IsPostBack)
				{
					
					PopulateScreen(ExchAccID);
				}
			}
			else
				throw new Exception("Invalid Query String passed - Needs Exchange Accounts ID.");


		
	}

	private void PopulateScreen(int ID)
	{
		ExchangeAccounts ea = new ExchangeAccounts();
		OleDbConnection cn = null;

		try
		{
			ClearScreen();

			if(ea.GetRecord(ID, ref cn))
			{
				txtEmailAddress.Text = ea.EmailAddress;
				txtFirstName.Text = ea.FirstName;
				txtSurname.Text = ea.Surname;
				cboUserType.SelectedValue = Convert.ToString(ea.UserStatus);
				txtPassword.Text = ea.Password;
			}

		}
		catch(Exception ex)
		{
			Common.PEH("PopulateScreen", "frm4-02", ex.Message);
		}
	}

	private void ClearScreen()
	{
		try
		{
			txtEmailAddress.BackColor = System.Drawing.Color.PowderBlue;
			txtFirstName.BackColor = System.Drawing.Color.PowderBlue;
			txtSurname.BackColor = System.Drawing.Color.PowderBlue;
			cboUserType.BackColor = System.Drawing.Color.PowderBlue;
			txtPassword.BackColor = System.Drawing.Color.PowderBlue;

			txtEmailAddress.Text = "";
			txtFirstName.Text = "";
			txtSurname.Text  = "";
			cboUserType.SelectedValue = "0"; //First entry in list
			txtPassword.Text = "";

			System.Threading.Thread.Sleep(500);

			txtEmailAddress.BackColor = System.Drawing.Color.White;
			txtFirstName.BackColor = System.Drawing.Color.White;
			txtSurname.BackColor = System.Drawing.Color.White;
			cboUserType.BackColor = System.Drawing.Color.White;
			txtPassword.BackColor = System.Drawing.Color.White;

		}
		catch(Exception ex)
		{
			Common.PEH("PopulateScreen", "frm4-02", ex.Message);
		}
	}

	private bool GetScreenData(ref ExchangeAccounts ea)
	{

		try
		{
			
			ea.EmailAddress = txtEmailAddress.Text;
			ea.FirstName = txtFirstName.Text;
			ea.Surname = txtSurname.Text;
			ea.UserStatus = Convert.ToInt32(cboUserType.SelectedValue);

			if(txtPassword.Text != "")
				ea.Password = txtPassword.Text;
			else
			{
				string script = "window.onload = function(){ alert('";
				script += "Blank Password is not allowed, please try again.";
				script += "')};";
				ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
				return false;
			}

			

			return true;
		}
		catch(Exception ex)
		{
			Common.PEH("GetScreenData", "frm4-02", ex.Message);
			return false;
		}
	}

	protected void imgButtClear_Click(object sender, ImageClickEventArgs e)
	{
		txtEmailAddress.Text = "";
	}

	private bool SaveExchangeAccount()
	{
		ExchangeAccounts ea = new ExchangeAccounts();
		OleDbConnection cn = null;

		try
		{
			if(ExchAccID != 0)
			{

				if(ValidateScreenData())
				{

					//We are modifying an existing record so get existing data into ea and then 
					//update the few fields we are editing here to their on screen changes.
					if(ea.GetRecord(ExchAccID, ref cn))
						if(GetScreenData(ref ea))
							ea.AddRecord(ExchAccID, true, ref cn);

				} //If screen not validated then we don't proceed to amend record.

			}

			PopulateScreen(ExchAccID);

			return true;
		}
		catch(Exception ex)
		{
			Common.PEH("SaveExchangeAccount", "frm4-02", ex.Message);
			return false;
		}
	}

	/// <summary>
	/// Validates that none of the screen items that are text are left blank and also
	/// that the drop down lost has something other than Nothing Selected.
	/// </summary>
	/// <returns>True if screen is Valid, False if not.</returns>
	private bool ValidateScreenData()
	{
		string strStartText = "Unable to save changes for the following reasons: \\n";
		string strText = "";

		try
		{

			if(txtEmailAddress.Text == "")
				strText += "\\nEmail Address is not completed, ";

			if(txtFirstName.Text == "")
				strText += "\\nFirst Name is not completed, ";

			if(txtSurname.Text == "")
				strText += "\\nSurname is not completed, ";

			if(cboUserType.SelectedValue == "0")
				strText += "\\nUser Type is not completed. ";

			if(txtPassword.Text == "")
				strText += "\\nPassword is not completed. ";

			if(strText != "")
			{
				string script = "window.onload = function(){ alert('";
				script += strStartText;
				script += strText;
				script += "')};";
				ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
				return false;
			}
			else
				return true;

		}
		catch(Exception ex)
		{
			Common.PEH("ValidateScreenData", "frm4-02", ex.Message);
			return false;
		}
	}

	protected void Save_Click(object sender, ImageClickEventArgs e)
	{
		string message = "";

		try
		{
			if(SaveExchangeAccount())
			{
				message = "Information saved successfully.";
			}
			else
			{
				message = "Information NOT saved.\\nPlease correct and try again.";
			}

			string script = "window.onload = function(){ alert('";
			script += message;
			script += "')};";
			ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);

		}
		catch(Exception ex)
		{
			Common.PEH("SaveExchangeAccount", "frm4-02", ex.Message);
		}
	}
}

Open in new window

ASKER CERTIFIED SOLUTION
kaufmed

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Siv

ASKER
Many thanks for posting this I am trying to implement it at the moment and will get back to you when I have got it working.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Siv

ASKER
Hmm, It works but messes up my screen design, because the change of class obliterates the text boxes which use a lot of classes to fit the page design.
kaufmed

The CssClass property that I referenced above is an absolute string:  whatever you assign to it, those are the classes that get applied when the textbox is rendered. If you want to keep your existing classes, then you can simply do an append rather than a direct assignment:

e.g.

this.TextBox1.CssClass += " myClass";

Note the additional + and space in the above line.
Siv

ASKER
I cracked it.  I did this:

This script was added to the aspx page:
    <script type="text/javascript">
        function sbc(OnOrOff) {
            if (OnOrOff)
            {
                var v = document.getElementById("<%=txtEmailAddress.ClientID%>");
                v.style.backgroundColor = "PowderBlue";
                var v = document.getElementById("<%=txtFirstName.ClientID%>");
                v.style.backgroundColor = "PowderBlue";
                var v = document.getElementById("<%=txtSurname.ClientID%>");
                v.style.backgroundColor = "PowderBlue";
                var v = document.getElementById("<%=txtPassword.ClientID%>");
                v.style.backgroundColor = "PowderBlue";
            }
            else
            {
                var v = document.getElementById("<%=txtEmailAddress.ClientID%>");
                v.style.backgroundColor = "White";
                var v = document.getElementById("<%=txtFirstName.ClientID%>");
                v.style.backgroundColor = "White";
                var v = document.getElementById("<%=txtSurname.ClientID%>");
                v.style.backgroundColor = "White";
                var v = document.getElementById("<%=txtPassword.ClientID%>");
                v.style.backgroundColor = "White";

            }
        }
    </script>

Open in new window


I then added this call to the OnClientClick of the Save button:

<asp:ImageButton ID="Save" runat="server" src="images/icon-save.png" OnClientClick="javascript:sbc(true);" OnClick="Save_Click" />

Open in new window


Then in my code behind Save_Click routine I put this:

	protected void Save_Click(object sender, ImageClickEventArgs e)
	{
		string message = "";

		try
		{
			if(SaveExchangeAccount())
			{
				ClientScript.RegisterStartupScript(this.GetType(), "sbcCall", "sbc(false);", true);
			}
			else
			{
				message = "Information NOT saved.\\nPlease correct and try again.";
				string script = "window.onload = function(){ alert('";
				script += message;
				script += "')};";
				ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);

			}


		}
		catch(Exception ex)
		{
			Common.PEH("Save_Click", "frm4-02", ex.Message);
		}
	}

Open in new window


So what happens is as follows:

  1. On the client side as you click the button to save the OnClientClick fires and calls my function to set the background to pale blue.
  2. The OnClick calls my code behind save function and after the code is saved I do this call to set it back ClientScript.RegisterStartupScript(this.GetType(), "sbcCall", "sbc(false);", true);
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Siv

ASKER
Thanks for your help. Although I used my own solution in the end, your solution would have worked once you explained that you could use the += on the class statement.