Button Click event occurs when it is disabled - c#

I'm pretty new at C#. But have experience in C, Python etc.
here is my question.
I have a GUI which has 2 forms.
the First form asks for a serial number of the unit and the second one is where the main test occurs.
In the 2nd form, there is a stage when I wait for the controller (DUT) to boot up so that I can get the bootup information.
I got most of the code working, but here the issue.
I disable the "Next" button until the user powercycles the unit. But, even with the button disabled, the click event occurs (when the user clicks the disabled button) and based on the number of click he does, the SW validates the clicks and skips the next stage/s.
how can I sort this out? Or, is there another better way to code this?
here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WIFI_DMX_TEST
{
public partial class form_test : Form
{
int x = 0;
int MAX_TEST_STATES = 15; //Set the number of test states.
string Rx_String;
test_instructions test_intsructions = new test_instructions(); //Create a new instance of the class test_instructions
public form_test()
{
InitializeComponent();
but_test_next_Click(null, null); //Call the but_test_next_Click event
Serial_INIT();
}
public void but_test_next_Click(object sender, EventArgs e)
{
if ((x <= MAX_TEST_STATES) && (but_test_next.Enabled == true))
{
if (x == 0)
{
textBox1.Text = test_intsructions.check_unit;
//load picture here showing unit
}
else if (x == 1)
{
textBox1.Text = test_intsructions.connect_cables;
//load picture here showing cables to connect
}
else if (x == 2)
{
textBox1.Text = test_intsructions.powerup_unit;
//load picture here showing unit powerup
}
else if (x == 3)
{
but_test_next.Enabled = false; //Disable the Next button
if (Rx_String == null) //check if the Rs232 info is empty
{
MessageBox.Show("No DUT info available. Please powercycle the unit", "Error: No data", MessageBoxButtons.OK, MessageBoxIcon.Error);
while (Rx_String == null) ; //Sit here doing nothing and wait till info is available
but_test_next.Enabled = true;
}
textBox1.Text = test_intsructions.program_unit; //Show next instruction.
//put programming function here.
//Put info here showing the unit has been programmed successfully or not.
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 4)
{
textBox1.Text = test_intsructions.reset_unit;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 5)
{
textBox1.Text = test_intsructions.query_colour_R;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 6)
{
textBox1.Text = test_intsructions.query_colour_G;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 7)
{
textBox1.Text = test_intsructions.query_colour_B;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 8)
{
textBox1.Text = test_intsructions.query_colour_W;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 9)
{
textBox1.Text = test_intsructions.acclerometer_mode;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 10)
{
textBox1.Text = test_intsructions.STL_mode_Sens_Low;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 11)
{
textBox1.Text = test_intsructions.STL_mode_Sens_High;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 12)
{
textBox1.Text = test_intsructions.test_mode;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 13)
{
textBox1.Text = test_intsructions.control_output;
//if failed, then log this error and WIFI controller info in the Log file.
}
else if (x == 14)
{
textBox1.Text = test_intsructions.powerdown_unit;
}
else if (x == 15)
{
textBox1.Text = test_intsructions.disconnect_cables;
}
//x++;
if (!((x == 3) && (but_test_next.Enabled == false)))
{
x++;
//but_test_next.Enabled = true;
}
//but_test_next.Enabled = true;
}
}
private void but_test_exit_Click_1(object sender, EventArgs e)
{
Serial_Close();
this.Close();
this.Hide();
form_startup f1 = new form_startup();
f1.ShowDialog();
}
private void program_unit()
{
}
class test_instructions
{
public string check_unit
{
get { return "Check DUT for any obvious faults"; }
set { }
}
public string connect_cables
{
get {return "Connect cables to the DUT";}
set {}
}
public string powerup_unit
{
get { return "Powerup the DUT"; }
set {}
}
public string program_unit
{
get { return "Programming the DUT"; }
set { }
}
public string reset_unit
{
get {return "Reset the unit";}
set {}
}
public string query_colour_R
{
get { return "Is the LED RED ON?"; }
set {}
}
public string query_colour_G
{
get {return "Is the LED GREEN ON?";}
set {}
}
public string query_colour_B
{
get {return "Is the LED BLUE ON?";}
set {}
}
public string query_colour_W
{
get {return "Is the LED WHITE ON?";}
set {}
}
public string acclerometer_mode
{
get { return "Accelerometer mode: Move the unit and check if the Lights change colour" ;}
set { }
}
public string STL_mode_Sens_Low
{
get { return "Set sensitivity to Low"; }
set { }
}
public string STL_mode_Sens_High
{
get { return "Set sensitivity to High"; }
set { }
}
public string test_mode
{
get { return "Press the test mode and check if lights are moving between R,G,B and W"; }
set { }
}
public string control_output
{
get { return "Check if Control output is working as expected."; }
set { }
}
public string powerdown_unit
{
get { return "Switch OFF the jig"; }
set { }
}
public string disconnect_cables
{
get { return "Disconnect cables and remove DUT"; }
set { }
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
Rx_String = serialPort1.ReadExisting();
this.Invoke(new EventHandler(DisplayText));
}
private void DisplayText(object sender, EventArgs e)
{
textBox2.AppendText(Rx_String);
}
private void Serial_INIT ()
{
serialPort1.PortName = "COM3";
serialPort1.BaudRate = 9600;
serialPort1.Open();
}
private void Serial_Close()
{
serialPort1.Close();
}
private void form_test_FormClosing(object sender, FormClosingEventArgs e)
{
Serial_Close();
}
}
}
cheers,
Mat

I didn't fully understand what you mean by disabling the button.
if you did the following it should work:
NextBtn.IsEnabled = false;
NextBtn.Visibility = Visibility.Collapsed;
Otherwise, you can simply disable the method by creating a bool:
bool hasOccured;
Private void Reason_Occured(EventArgs)
{
hasOccured = true;
}
private void NextBtn_Click(Args)
{
if(hasOccured) return;
//code chunk
}

Sorry for the late reply.
I managed to fix this issue. Seems like I had to use a Switch, Case statement rather than If statements.
Cheers for all your help
Mat
:D

Related

Passing Object from Class to Windows Form

I've got four main files in play here: Form 1, which is called frmLogin, Form2, which is called frmUserHome, a class called DbConnector.cs and a class called BankAccount.cs
The program works as follows: Form1 calls method from DBConnector -> DB Connector method fills an object and it's variables which is instantiated in DBConnector. This object is of class BankAccount.cs
Then, after the method finishes and if successful, Form1 instantiates Form2 and it opens. In form2 is where I want to access the object that was created in the DBconnector class. How do I do this? I've tried instantiating new objects of BankAccount.cs in there, I've tried all these different constructor stuff I've seen on here. Nothing seems to be working.
For reference: the object is populated when it runs in Dbconnector. However, when I try to receive data when I use it in Form2, all of the fields are NULL.
I've made countless adjustments from reading different posts on here so the code is rightfully a mess now and probably extremely unorganised.
Here's the main portions of my code below:
Form1
namespace BankingSystem
{
public partial class frmLogIn : Form
{
public BankAccount myBankAccount = new BankAccount();
dbConnector newConnector;
public frmLogIn()
{
InitializeComponent();
timerMain.Enabled = true;
timerMain.Start();
}
private void btnLogIn_Click(object sender, EventArgs e)
{
try
{
newConnector.CheckDetailsLogin(accountNumTextBox.Text, pinNumTextBox.Text);
frmUserHome UserHome = new frmUserHome();
MessageBox.Show("Success! Happy Banking!");
UserHome.ShowDialog();
}
catch
{
MessageBox.Show("Failed - incorrect login details.");
}
}
}
}
DBConnector Class:
namespace BankingSystem
{
public class dbConnector
{
Boolean isCorrect = false;
private static SQLiteConnection sqlconnConnection;
public BankAccount myBankAccount = new BankAccount();
public DataSet myAppDataSet = new DataSet(); // created for you to use and push data into
public dbConnector(string strFilePath)
{
try
{
sqlconnConnection = new SQLiteConnection("Data Source=" + strFilePath);
}
catch (Exception ex)
{
throw new Exception("DbConnector initialisation unsuccessful:\n" + ex.Message);
}
}
public void CheckDetailsLogin(string strAccno, string strPin)
{
// this is where check ou the boiler plate code and adjst to my APP.
try
{
DataTable dtUser = new DataTable();
sqlconnConnection.Open();
string strQuery2 = #"SELECT * FROM Accounts WHERE Account_Number='"+ strAccno +"' AND PIN='"+ strPin +"';"; // example of a parametrised SQL statement.
SQLiteCommand sqlcomCommand2 = new SQLiteCommand(strQuery2, sqlconnConnection);
SQLiteDataAdapter sqldatadptAdapter = new SQLiteDataAdapter(sqlcomCommand2); // local SQL data Adaptor
try
{
sqldatadptAdapter.Fill(dtUser);
}
catch (Exception ex)
{
// Exception will the "thrown"/Raised when there was a problem
throw new Exception($"SELECT unsuccessful:\n{ex.Message}");
}
finally
{
sqlconnConnection.Close();
}
if (dtUser.Rows.Count == 0)
{
// the record set comes back with no records found, an empty Datatable with no rows
// means there was no data matching your query
throw new Exception("No Such Bank user found");
}
else
{
// change to your applications needs
// Rows[0] - we are expecting at least 1 row, and its basically an array so we address
// the first element with 0
// Rows[0]["fieldnamefromDB"] <- referencing the column in the DB
//this.strID = strUserID;
myBankAccount.AccountNumber = dtUser.Rows[0]["Account_Number"].ToString();
myBankAccount.AccountPin = dtUser.Rows[0]["PIN"].ToString();
myBankAccount.AccountBalance = Convert.ToDecimal(dtUser.Rows[0]["Balance"]);
myBankAccount.AccountHolder = dtUser.Rows[0]["First_Name"].ToString();
myBankAccount.AccountAddress = dtUser.Rows[0]["Home_Address"].ToString();
myBankAccount.MyAccountGUID = dtUser.Rows[0]["GUID"].ToString();
if (myBankAccount.AccountNumber == strAccno && myBankAccount.AccountPin == strPin)
{
isCorrect = true;
}
else
{
isCorrect = false;
}
//myLocalBankAccUsr
}
}
catch (Exception ex)
{
// exception thrown for the whole method or function
throw new Exception($"User(string):\n{ex.Message}");
}
}
BankAccount.cs class
namespace BankingSystem
{
public class BankAccount
{
private string accountNumber;
private decimal accountBalance;
private string accountHolder;
private string accountPhoneNumber;
private string accountAddress;
private string accountPin;
private string myAccountGUID;
// private string AccountHolderGUID;
// private string AccountTypeGUID;
public string AccountNumber
{
get { return accountNumber; }
set { accountNumber = value; }
}
public decimal AccountBalance
{
get { return accountBalance; }
set { accountBalance = value; }
}
public string AccountHolder
{
get { return accountHolder; }
set { accountHolder = value; }
}
public string AccountPhoneNumber
{
get { return accountPhoneNumber; }
set { accountPhoneNumber = value; }
}
public string AccountAddress
{
get { return accountAddress; }
set { accountAddress = value; }
}
public string AccountPin
{
get { return accountPin; }
set { accountPin = value; }
}
public string MyAccountGUID
{
get { return myAccountGUID; }
set { myAccountGUID = value; }
}
public Boolean CanWithDrawAmount(decimal AmountToTransfer)
{
if (AmountToTransfer > this.AccountBalance){
return false;
}else
{
return true;
}
}
public void UpdatePIN()
{
// connect to bank DB connector
// send it the new pin
// SQL update command
}
}
}
Here is Form2:
namespace BankingSystem
{
public partial class frmUserHome : Form
{
public frmUserHome()
{
InitializeComponent();
tabMainForm.Appearance = TabAppearance.FlatButtons;
tabMainForm.ItemSize = new Size(0, 1);
tabMainForm.SizeMode = TabSizeMode.Fixed;
timerMain.Enabled = true;
timerMain.Start();
}
private void frmUserHome_Load(object sender, EventArgs e)
{
labelWelcome.Text = "Welcome "; //newMainBank.AccountHolder;
}
The 'labelWelcome.Text = "Welcome" is where I want the name stored inside the object to be used. So it should ideally access the BankAccount class, access the AccountHolder field and use that field to concat onto the end of the 'Welcome' text. However, it just shows 'Welcome' and no name on the end, when I run the program (because all values get reset to null in form2.. for some reason)
Below I have updated the code for Form1 and Form2.
Form 1
namespace BankingSystem
{
public partial class frmLogIn : Form
{
dbConnector newConnector;
public frmLogIn()
{
InitializeComponent();
newConnector = new dbConnector(**pass str file path**);
timerMain.Enabled = true;
timerMain.Start();
}
private void btnLogIn_Click(object sender, EventArgs e)
{
try
{
newConnector.CheckDetailsLogin(accountNumTextBox.Text, pinNumTextBox.Text);
frmUserHome UserHome = new frmUserHome(newConnector.myBankAccount);
MessageBox.Show("Success! Happy Banking!");
UserHome.ShowDialog();
}
catch
{
MessageBox.Show("Failed - incorrect login details.");
}
}
}
}
Form 2
namespace BankingSystem
{
public partial class frmUserHome : Form
{ public BankAccount _bankAccount;
public frmUserHome(BankAccount bankAccount)
{
InitializeComponent(); _bankAccount = bankAccount;
tabMainForm.Appearance = TabAppearance.FlatButtons;
tabMainForm.ItemSize = new Size(0, 1);
tabMainForm.SizeMode = TabSizeMode.Fixed;
timerMain.Enabled = true;
timerMain.Start();
}
private void frmUserHome_Load(object sender, EventArgs e)
{
labelWelcome.Text = "Welcome "+ bankAccount.AccountHolder;
}

Unity - Advertisment called multiple times

I'm having this problem using Unity's Advertisment. Specifically after watching the video and clicking the X button to close the video, I should give the prize to the player (go to the next level). The problem is that the OnUnityAdsDidFinish function calls if (showResult == ShowResult.Finished) multiple times. What am I doing wrong? how do I call the FindObjectOfType () .LoadNextLevel () function once; ? Thank you in advance
public class UnityAdsInterstitial : MonoBehaviour, IUnityAdsListener
{
private string gameID = "******";
//nome scelto nella DashBoard di Unity
private string interstitialID = "interstitial";
private string myPlacementId = "rewardedVideo";
public int randomHighValue = 30;
private bool TestMode = true;
private bool adsClosed = false;
public Button _button;
private void Awake()
{
_button = GetComponent<Button>();
}
void Start()
{
Debug.Log("Ads start");
_button = GameObject.Find("StartAds").GetComponent<Button>();
_button.interactable = Advertisement.IsReady(myPlacementId);
if (_button) _button.onClick.AddListener(ShowRewardedVideo);
Advertisement.Initialize(gameID, TestMode);
Advertisement.AddListener(this);
if (adsClosed)
{
adsClosed = false;
}
}
public void ShowInterstitial()
{
if (Advertisement.IsReady(interstitialID) )
{
Advertisement.Show(interstitialID);
}
}
public void ShowRewardedVideo()
{
if (Advertisement.IsReady(myPlacementId))
{
Debug.Log("Rewarded video is Ready");
Advertisement.Show(myPlacementId);
}
else
{
Debug.Log("Rewarded video is not ready at the moment! Please try again later!");
}
}
public void HideBanner()
{
Advertisement.Banner.Hide();
}
public void OnUnityAdsReady(string placementdID)
{
if (placementdID == interstitialID)
{
Debug.Log("InterstitialIsReady");
}
if (placementdID == myPlacementId)
{
Debug.Log("RewardedIsReady");
_button.interactable = true;
}
}
public void OnUnityAdsDidFinish(string placementdID, ShowResult showResult)
{
if (showResult == ShowResult.Finished)
{
// Reward the user for watching the ad to completion.
if (!adsClosed)
{
adsClosed = true;
FindObjectOfType<LevelLoader>().LoadNextLevel();
}
}
else if (showResult == ShowResult.Skipped)
{
// Do not reward the user for skipping the ad.
}
else if (showResult == ShowResult.Failed)
{
Debug.LogWarning("The ad did not finish due to an error.");
}
}
public void OnUnityAdsDidError(string message)
{
Debug.Log("OnUnityAdsDidError");
}
public void OnUnityAdsDidStart(string message)
{
Debug.Log("OnUnityAdsDidStart");
}
I would start my investigation by checking the placement id (in case there are more placements)
Checking that the callback is for the proper placement id
if (showResult == ShowResult.Finished && placementId == myPlacementId)
{
// Reward the user for watching the ad to completion.
if (!adsClosed)
{
adsClosed = true;
FindObjectOfType<LevelLoader>().LoadNextLevel();
}
}
The second would be that I only have one active instance of UnityAdsInterstitial. You can check this in debug mode by the reference of the object. If more than one instance starts from somewhere else in your code, then you should just limit to one.

Wait for input from a textbox, similar to Console.Read()

So I'm trying to have the user enter some input which derives its data from a class variable. The user will enter their input though a textbox and hit return when finished, causing the event to update the class variable. However, my issue is figuring out how to send a signal from the EventHandler to continue the process. I know a simple solution would be to put the code triggered inside the event method, but I want to use multiple methods with this textbox and input.
Here's what my code currently looks like:
public partial class Form1 : Form
{
private String input;
public Form1()
{
InitializeComponent();
outbox.AppendText("Hello World!"); //outbox is the display
start();
}
private void inbox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
input = inbox.Text; //inbox is the textbox for input;
}
else
{
//do nothing
}
}
private void start()
{
outbox.AppendText("Enter one, two, three or four.");
//---
//this is where the issue arises
//---
if (text_input.Equals("one"))
{
outbox.AppendText("Sunflowers");
}
else if (text_input.Equals("two))
{
outbox.AppendText("Tulips");
}
else if (text_input.Equals("three"))
{
outbox.AppendText("Daisies");
}
else if (text_input.Equals("four"))
{
outbox.AppendText("Poppies");
}
else if (text_input.Equals("quit"))
{
Application.Exit();
}
else
{
outbox.AppendText("Try again.");
start();
}
}
}
What can I do to pause the program until the user hits return and passes a string to input?
You should probably separate the actions before user input from actions that should happen after user input.
If you want to implement different behaviours then it may help to store the program state, including the action you want to perform after user input is complete.
Try something like this, and adapt as required:
public partial class Form1 : Form
{
private String input;
private enum InputMode {
None,
Numbers
}
private class ModeDefinition{
public InputMode Mode {get; private set; }
public string Prompt{get; private set; }
public Action ActionMethod{get; private set; }
public ModeDefinition(InputMode mode, string prompt, Action actionMethod)
{
this.Mode = mode;
this.Prompt = prompt;
this.ActionMethod = actionMethod;
}
}
private InputMode currentMode;
private Dictionary<InputMode,ModeDefinition> modeDefinitions;
public Form1()
{
InitializeComponent();
outbox.AppendText("Hello World!"); //outbox is the display
initialise();
currentMode = InputMode.Numbers;
commenceAction(modeDefinitions[currentMode]);
}
private void initialise(){
modeDefinitions = new Dictionary<InputMode,ModeDefinition>();
var def1 = new ModeDefinition(InputMode.Numbers, "Enter one, two, three or four.", numbersAction);
modeDefinitions.Add(InputMode.Numbers, def1);
}
private void commenceAction(ModeDefinition modeDefinition){
outbox.AppendText(modeDefinition.Prompt);
}
private void inbox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
input = inbox.Text; //inbox is the textbox for input;
var currentMode = modeDefinitions[currentMode];
// Execute the mode action
currentMode.ActionMethod();
}
else
{
//do nothing
}
}
private void numbersAction(){
if (text_input.Equals("one"))
{
outbox.AppendText("Sunflowers");
}
else if (text_input.Equals("two))
{
outbox.AppendText("Tulips");
}
else if (text_input.Equals("three"))
{
outbox.AppendText("Daisies");
}
else if (text_input.Equals("four"))
{
outbox.AppendText("Poppies");
}
else if (text_input.Equals("quit"))
{
Application.Exit();
}
else
{
outbox.AppendText("Try again.");
var currentMode = modeDefinitions[currentMode];
outbox.AppendText(modeDefinition.Prompt);
}
}
}
Don't know my solution is what y need
Firstly , u declare property like this
private string _content;
private string content
{
set
{
if (value != _content)
{
_content = value;
checkContent();
}
}
get
{
return _content;
}
}
private void checkContent()
{
if (content.Equals("one"))
{
outbox.AppendText("Sunflowers");
}
else if (content.Equals("two"))
{
outbox.AppendText("Tulips");
}
else if (content.Equals("three"))
{
outbox.AppendText("Daisies");
}
else if (content.Equals("four"))
{
outbox.AppendText("Poppies");
}
else if (content.Equals("quit"))
{
Application.Exit();
}
else
{
outbox.AppendText("Try again.");
start();
}
}
private void start()
{
outbox.AppendText("Enter one, two, three or four.");
}
private void inbox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
content = inbox.Text; //inbox is the textbox for input;
}
else
{
//do nothing
}
}
}

Console C# check for internet availability and wait until it is not available

I have been searching for the code which will help me if the internet connection breaks in between.
I am having a console app which takes data from database and sends mail in bulk. Now while sending mails if internet connection fails than I want to wait until internet is available.
I got good ans here
public static void ConnectToPUServer()
{
var client = new WebClient();
while (i < 500 && networkIsAvailable)
{
string html = client.DownloadString(URI);
//some data processing
Console.WriteLine(i);
i++;
URI = "http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/" + i + "/";
}
Console.WriteLine("Complete.");
writer.Close();
}
static void NetworkChange_NetworkAvailabilityChanged(object sender,NetworkAvailabilityEventArgs e)
{
networkIsAvailable = e.IsAvailable;
if (!networkIsAvailable)
{
Console.WriteLine("Internet connection not available! We resume as soon as network is available...");
}
else
{
ConnectToPUServer();
}
}
This is not exactly what I want. But I want to apply something similar to this. Can anybody help me how to implement this? I mean what is ConnectToPUServer and when NetworkChange_NetworkAvailabilityChanged will be executed and what namespace to be used?
you can use the below mentioned code for it you have to use
using System.Net.NetworkInformation;
public partial class MainWindow : Window
{
public bool IsAvailable { get; set; }
public MainWindow()
{
InitializeComponent();
NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
}
void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
IsAvailable = e.IsAvailable;
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
if (IsAvailable)
{
WebBrowser1.Navigate(TextBox1.Text);
}
else
{
MessageBox.Show("Your Popup Message");
}
}
}

C# Sql Server "loading window"

This is my first post here, but I've using this site regularly to help me with my own app's, and I should say that this site has been a great help to me, so thanks to everyone.
Now my question:
I'm developing my first software app that exchanges data between a sql server and the app itself. It's beeing developed in C#. Saving or retreiving data from the sql server database is no problem.
What I want is a way to inform the user of the delay between the local machine (where the app is installed) and the server. I can make some animations or simply display some text messages. What I need help with is how to create the code that activates/fires/runs when that server communication time is running.
If you can't understand the idea, picture a video game. When it's loading (in some games) you can see the loading screen before the game starts. I need some code that displays that "loading window" when the the app is downloading or uploading data from/to the server.
I would appreciate any code example or web site recommendation.
PS: Sorry for the extensive text, but I want to make sure everyone understand so I don't have to repeat it again :P
How do I implement a progress bar in C#?
How to create a smooth progress bar in Visual C#
ProgressBar Class
I have developed a simple PleaseWait class 2 years ago, but I didn't update this class, It works very well, have look hope this will give you an idea to implement your logic.
public partial class frmWait : Form
{
public frmWait()
{
InitializeComponent();
}
bool _isMoving = false;
int _moveStart_x = 0;
int _moveStart_y = 0;
private void tmrProgress_Tick(object sender, EventArgs e)
{
if (barProgress.Value == barProgress.Maximum)
barProgress.Value = barProgress.Minimum;
else
barProgress.Value += 1;
}
private void btnCancel_Click(object sender, EventArgs e)
{
Close();
PleaseWait.Abort();
}
protected override CreateParams CreateParams
{
get
{
System.Windows.Forms.CreateParams p = base.CreateParams;
p.ClassStyle += 0x20000;
p.ExStyle += 0x8000000;
return p;
}
}
protected override void WndProc(ref Message m)
{
const int WM_NCHITTEST = 132;
base.WndProc(ref m);
switch (m.Msg)
{
case WM_NCHITTEST:
if (m.Result.ToInt32() == 1)
m.Result = new IntPtr(2);
break;
}
}
private void panelEx1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_isMoving = true;
_moveStart_x = e.X;
_moveStart_y = e.Y;
}
}
private void panelEx1_MouseUp(object sender, MouseEventArgs e)
{
_isMoving = false;
}
private void pnlContainer_MouseMove(object sender, MouseEventArgs e)
{
if (_isMoving)
this.Location = new Point(Location.X + e.X - _moveStart_x, Location.Y + e.Y - _moveStart_y);
}
}
public class PleaseWait
{
#region Static Operations
private static Boolean _isAborted = false;
private static Boolean _isVisible = false;
private static frmWait _waitForm;
private static String _waitingState = "";
private static Boolean _autoClose = false;
private static Boolean _cancelable = false;
private static System.Threading.Thread _waiterThred;
public delegate void CancelButtonPressed();
public static event CancelButtonPressed OnCancel;
public static Boolean AutoClose
{
get { return PleaseWait._autoClose; }
set { PleaseWait._autoClose = value; }
}
public static string WaitingState
{
get { return PleaseWait._waitingState; }
set { PleaseWait._waitingState = value; }
}
public static bool IsVisible
{
get { return _isVisible; }
internal set { _isVisible = value; }
}
public static void ShowPleaseWait()
{
ShowPleaseWait("", _autoClose, false);
}
public static void ShowPleaseWait(string waitingState)
{
ShowPleaseWait(waitingState, _autoClose, false);
}
public static void ShowPleaseWait(bool autoClose)
{
ShowPleaseWait("", autoClose, false);
}
public static void ShowPleaseWait(string waitingState, bool autoClose, bool cancelable)
{
if (_waiterThred != null)
{
if (_isVisible)
{
// the please wait it woking, just continue and apply the changes
_waitingState = waitingState;
_autoClose = autoClose;
_cancelable = cancelable;
return;
}
else
{
_waiterThred.Abort();
_waiterThred = null;
}
}
_waitingState = waitingState;
_autoClose = autoClose;
_cancelable = cancelable;
_isAborted = false;
_isVisible = false;
if (_autoClose)
Application.Idle += new EventHandler(Application_Idle);
_waiterThred = new System.Threading.Thread(DisplayWaitingForm);
_waiterThred.IsBackground = true;
_waiterThred.Name = "Please Wait....";
_waiterThred.Start();
Application.DoEvents();
}
public static void Abort()
{
_isAborted = true;
}
private static void Application_Idle(object sender, EventArgs e)
{
if (_autoClose)
_isAborted = true;
}
private static void DisplayWaitingForm()
{
if (_waitForm != null)
{
if (!_waitForm.IsDisposed)
_waitForm.Dispose();
_waitForm = null;
_isVisible = false;
}
try
{
if (_isAborted)
return;
_waitForm = new frmWait();
if (_cancelable)
{
_waitForm.btnCancel.Enabled = true;
_waitForm.btnCancel.Click += new EventHandler(btnCancel_Click);
}
try
{
_isVisible = true;
_waitForm.Show();
_waitForm.Focus();
while (!_isAborted)
{
System.Threading.Thread.Sleep(15);
_waitForm.lblMessage.Text = _waitingState;
Application.DoEvents();
_waitForm.lblMessage.Text = _waitingState;
}
_isVisible = false;
}
finally
{
FreeWaitingForm();
}
}
finally
{
_isVisible = false;
}
}
static void btnCancel_Click(object sender, EventArgs e)
{
if (_waitForm.InvokeRequired)
{
_waitForm.BeginInvoke(new EventHandler(btnCancel_Click), new object[] { e });
}
else
{
if (OnCancel != null)
OnCancel.Invoke();
}
}
private static void FreeWaitingForm()
{
_waitingState = "";
_isVisible = false;
if (_waitForm == null)
{
return;
}
_waitForm.Hide();
if (!_waitForm.IsDisposed)
_waitForm.Dispose();
_waitForm = null;
}
#endregion
}
use like following code :
PleaseWait.ShowPleaseWait("Please wait", true, false);
// If second param is true then it will close the form automatically.
// If third param is true the it will expose a cancel button, so you can cancel your Asynchronous operations.
I didn't insert design code, you can understand by looking at code.
hope this help.
First let me thank you for your replies.
Toby your answer got me thinking about thread monitoring my sql connections but it was a bit tricky and confusing since the app is still in develop and will use a lot more connections.
S.Amani answer it wasn't quite what I want, but thanks to that I found a easier way. I created a form (could be anything else), placed a label saying: Saving To Data Base, took out the top bar, defined location and defined it's parent to be disabled when shown and enabled when closed. The following code is what I put inside my DataBaseInteractionClass
private Wait myCustomWaitDialog = new Wait(); // My Waiting form
private void SaveToDatabase(myObjectToSave obj) // Method called to save data do DB
{
// Create the connections and queries
(...)
// This is what I did
// Show Waiting Form
myCustomWaitDialog.Show();
// Instanciate the command that will carry the query and to DB
SqlCommand command = new SqlCommand(Queries.GetData(code), conn);
// This is important
//Create event that will fire when the command completes
command.StatementCompleted += new StatementCompletedEventHandler(command_StatementCompleted);
// Execute the transaction
SqlDataReader reader = command.ExecuteReader();
// Rest of the code (validations, close connections, try/catch, etc
(...)
}
void command_StatementCompleted(object sender, StatementCompletedEventArgs e)
{
// This is the method that closes my Waiting Dialog
myCustomWaitDialog.CloseDialog();
myCustomWaitDialog.Dispose();
}
It's not quite what I want yet, but is the best solution that I found so far. For now it will do :)
Anyway, thanks for the replies and I hope this helps someone else.

Categories