Solved

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

Posted on 2016-09-08
14
41 Views
Last Modified: 2016-09-09
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
0
Comment
Question by:Siv
  • 8
  • 6
14 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 41789686
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.
0
 

Author Comment

by:Siv
ID: 41789719
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.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 41789753
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/
0
 

Author Comment

by:Siv
ID: 41789823
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
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 41789858
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?
0
 

Author Comment

by:Siv
ID: 41790131
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
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 41790319
Sorry, what I mean is, when you push the button, does the entire page refresh, or does only part of the page refresh?
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:Siv
ID: 41790336
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

0
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
ID: 41791213
So if you've got a full postback going on (i.e. the entire page refreshes), then you could inject the Javascript (and/or JQuery) into the response. While the injection happens on the server, the execution happens on the client. It's been a while since I've done Web Forms, but if memory serves, you should be able to invoke the ClientScriptManager for the injection bits. I'll leave this for you to marinate over.

With the above said, I think a simpler way for you to accomplish this, although it may leave your DOM just a tad bit messier, would be to go ahead and add the blink script that I referenced above to your page. It will only execute against elements that have the "myClass" class value. But on your initial page display/load, none of the elements will have this class, so nothing will blink. When the data is posted back to the server, you can add the "myClass" class value to whatever controls you want to blink. (Note: You don't have to call it "myClass". You can call it whatever you like. I'm just using the parlance that already exists in that particular tutorial.)

e.g.

Markup
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication6._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

    <asp:Button ID="Button1" runat="server" Text="Submit" />

    <style>
        .blink {
            color: #FFF !important;
            background: #FC79CE;
            !important;
        }
    </style>
    <script>
        $(document).ready(function () {
            blink(".myClass", 25, 500); //blink anything that has a myClass on it
        });

        function blink(elem, times, speed) {
            if (times > 0 || times < 0) {
                if ($(elem).hasClass("blink"))
                    $(elem).removeClass("blink");
                else
                    $(elem).addClass("blink");
            }

            clearTimeout(function () {
                blink(elem, times, speed);
            });

            if (times > 0 || times < 0) {
                setTimeout(function () {
                    blink(elem, times, speed);
                }, speed);
                times -= .5;
            }
        }
    </script>
</asp:Content>

Open in new window


Code-Behind
using System;
using System.Web.UI;

namespace WebApplication6
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Page.IsPostBack)
            {
                this.TextBox1.CssClass = "myClass";
            }
        }
    }
}

Open in new window


 Example
0
 

Author Comment

by:Siv
ID: 41791460
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.
0
 

Author Comment

by:Siv
ID: 41791489
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.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 41791627
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.
0
 

Author Comment

by:Siv
ID: 41791638
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);
0
 

Author Closing Comment

by:Siv
ID: 41791645
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.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now