Site Hangs Before Method Execution - c#

I'm trying to build a simple application that will ask for input based on a provided set of terms. It begins with the click of a button:
protected void InventoryMoveButton_Click(object sender, EventArgs e)
{
DataDisplay.Text = "Inventory Move:";
isDataStringMode = false;
InstructionsLabel.Text = InventoryInstructions; //displays instruction text
InventoryMove();
}
Which displays some text and calls InventoryMove().
void InventoryMove()
{
string[] keyList = { "FROM", "TO", "QUANTITY" }; //moving from somewhere to somewhere
DataDisplay.Text = "hello from inventory move"; //this is a textbox
BuildScreen("Inventory Move", BuildKeyList(keyList));
}
The method provides a list of terms for which it will require values from the user to the method BuildScreen(). BuildKeyList() simply takes those terms and puts them into an ArrayList, which BuildScreen() accepts. BuildScreen() is defined as follows:
void BuildScreen(string action, ArrayList listOfKeys)
{
int input;
DataDisplay.Text += "lol hi from BuildScreen";
//DataTextBox.Text = "";
DataDisplay.Text = action + "\n";
//dataValues.Clear(); //empty previous values as they are not part of the current operation
foreach (string key in listOfKeys)
{
DataDisplay.Text += key + ": ";
input = readValidNumber();
DataDisplay.Text += input + "\n";
dataValues.Add(key, input);
}
}
The problem I'm having is that upon clicking the button, the InstructionsLabel text you see in my first bit of code never changes. So it seems the code is hanging at that point, but that could just be an error caused elsewhere before the text has the chance to change. Why is this code hanging when I click the button?

Related

How to execute a method with a button click

How can I add a function to a button that will run a method I've created. I want to write out an array into a message dialog box with a press of a button, but I don't seem to be getting anywhere so i turned to stackoverflow for some help, since googling didn't really help me with my problem.
static void Tractors(Tractor[] tractors)
{
for (int i = 0; i < tractors.Length; i++)
{
Console.WriteLine((i + 1) + ", " + tractors[i].ToString());
}
}
This is my function that writes out the table of "Tractors".
private void button1_Click(object sender, EventArgs e)
{
}
What should I write into the button1_click method so that it would work?
You need to bind the event handler with the button control and write the logic inside this event handler. If its windows form application you can do like this.
this.button1 = new System.Windows.Forms.Button();
this.button1.Click += new System.EventHandler(this.button1_Click);
private void button1_Click(object sender, EventArgs e)
{
//Call your methods here
}
You would call Tractor() the exactly same way you call Console.WriteLine(). Both are static functions.
However the function is utterly messed up and propably not salvageable. The proper name would be printTractorsToConsole(). As it contains the Console.WriteLine() call, it is strongly tied to Console Applications - avoid tying functions to one Display Technology like that.
You need a more general function that creates and returns a string. You can then send that string to WriteLine(), assign it to Label.Text or wherever else you want the string to be. Strings primarily exist for intput from or output towards the user - and there is too many ways to get it to them.
//Not tested against a compiler, may contain syntax errors
static string TractorArrayToString(Tractor[] tractors){
string output = "";
for (int i = 0; i < tractors.Length; i++)
{
output += (i + 1) + ", " + tractors[i].ToString()) + Environment.NewLine;
}
return output;
}
But even function might be a bad idea, as that function would tie all representations to a single format. Generally you would write that loop directly into the Click Event. But this function looks like it is for printing for debug purposes, so it might work.

How to use functions step by step

Sorry for the strange title, I just don't know how to name this question.
So I have such a function say().
void say(string printedText) {
gameText.text = printedText;
}
And I need to use it several times. Something like this:
say("test text 1");
say("test text 2");
say("test text 3");
...
I need to change text by clicking Space button. Of course I need to use something like this:
if(Input.GetKeyDown(KeyCode.Space)) {
...
}
But I can't understand how to show text step by step. So for example if I click Space button once I should see "test text 1". Next click should show me "test text 2" etc.
How can I realise it? Thanks in advance.
Depending on your needs you could store different texts in a List<string> or maybe even Queue<string> and do
List example
// Add your texts in the editor or by calling texts.Add(someNewString)
public List<string> texts = new List<string>();
private int index = 0;
if(Input.GetKeyDown(KeyCode.Space))
{
// have a safety check if the counter is still within
// valid index values
if(texts.Count > index) say(texts[index]);
// increase index by 1
index++;
}
Array example
Basically the same as the List<string> but you can't add or remove elements "on the fly" (at least not that simple)
public string[] texts;
private int index = 0;
if(Input.GetKeyDown(KeyCode.Space))
{
// have a safety check if the counter is still within
// valid index values
if(texts.Length > index) say(texts[index]);
// increase index by 1
index++;
}
Queue example
public Queue<string> texts = new Queue<string>();
for adding a new text to the end of the queue do
texts.Enqueue(someNewString);
and then
if(Input.GetKeyDown(KeyCode.Space))
{
// retrieves the first entry in the queue and at the same time
// removes it from the queue
if(texts.Count > 0) say(texts.Dequeue());
}
Simple counter
If it is really just about having a different int value then yes simply use a field
private int index;
if(Input.GetKeyDown(KeyCode.Space))
{
// uses string interpolation to replace {0} by the value of index
say($"test text {0}", index);
// increase index by one
index++;
}
define a class field like this:
int count = 0;
and now everytime space is hit:
if(Input.GetKeyDown(KeyCode.Space)) {
say("test text " + count);
count = count + 1;
}
This Code:
if(Input.GetKeyDown(KeyCode.Space)) {
...
}
only works for Unity, In Visual Studio you'll have to create an Event to whatever object you want to do this, for example, if you want to call a void each time you press spacebar youll have to do this, it is easy: (Image below)
In the propieties window press the bolt icon and after double click on the event you want to create (samples): TextChanged, LocationChnaged, MouseMove, etc...
I will use KeyDown on the TextBox object
image
Now in your code this void should be generated
image
Inside this void i writed the code and this is how it looks:
(put int n = 1 before voids)
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Space)
{
//int n = 1; must be defined
textBox1.Text = "test text " + n;
n++;
}
}
Now each time you'll press or stay pressed spacebar the textbox will be filled with "test text " and the value will be 1 more each time.

While using Task.Delay for printing characters, how to prevent new KeyDown events occurring during print?

I have many form control click events and keydown events for user control on a game I'm building. Much of the game details provided is in text that is printed to a read only text box using a Task.Delay method for slow printing:
async public void delayPrintLine(TextBox console, string output)
{
string s = output;
char[] charArray = s.ToCharArray();
s = "";
for (int i = 0; i < charArray.Length; i++)
{
console.AppendText(charArray[i].ToString());
await Task.Delay(80);
}
console.AppendText(Environment.NewLine);
}
Currently with all my button clicks or KeyDown events, if you do them fast or hold the key down continuously the printing interrupts and mixes together. Also it's causing data problems like if holding down 'a' for attack, you end up getting 10x the exp intended and 10 prints of "You Win".
I want to rewrite my events to not handle any other events while things are still printing or functions processing. I have tried using a flag to check and the code seems to make full sense but makes no change to the performance.
Global Flag:
public bool activeAction = false;
Attack Button Example:
private void attackBtn_Click(object sender, EventArgs e)
{
if (!activeAction)
{
activeAction = true;
heroAttack();
currentHP.Text = "HP: " + hero.HP;
}
else
{
return;
}
activeAction = false;
}

How do I make one word in a text box end a program?

So one of the forms I have to create is where you enter a first and last name and then it splits the two names and puts them next to the appropriate labels, form design: https://gyazo.com/9b34dca0c1cd464fd865830390fcb743 but when the word stop is entered in any way e.g. Stop, StOp, sToP etc. it needs to end.
private void btnSeparate_Click(object sender, EventArgs e)
{
string strfullname, strgivenname, strfamilyname, strfirstname;
int int_space_location_one, int_space_location_two;
strfullname = txtFullName.Text;
int_space_location_one = strfullname.IndexOf(" ");
strgivenname = strfullname.Substring(0, int_space_location_one);
lblGivenEntered.Text = strgivenname;
strfirstname = strfullname.Remove(0, int_space_location_one + 1);
int_space_location_two = strfirstname.IndexOf(" ");
strfamilyname = strfirstname.Substring(int_space_location_two + 1);
lblFamilyEntered.Text = strfamilyname;
}
This is my current code, I have tried many different ways to get the word stop to end it but it wont work so that's why there is currently no code trying to stop the program, the main problem I get is because it is searching for a space between the first and last name and it obviously doesn't have one for one word it just crashes.
Any help with this would be amazing, thanks in advance.
Just hook up the TextChanged event and go like this:
private void TextChanged(Object sender, EventArgs e)
{
// If text, converted to lower-characters contains "stop" -> Exit
if(txtFullName.Text.ToLower().Contains("stop"))
{
// What I understand as "stopping it".
Application.Exit();
}
}
IF with "stop it" you mean to cancle the operation:
private void btnSeparate_Click(object sender, EventArgs e)
{
// If text, converted to lower-characters contains "stop" -> Exit
if (txtFullName.Text.ToLower().Contains("stop"))
{
// What I understand as "stopping it".
Application.Exit();
}
else
{
// Your code inside the else block
}
}
Short version of everything: Also covering no spaces problem
private void btnSeparate_Click(object sender, EventArgs e)
{
// Save how many words are inside
int wordsInText = txtFullName.Text.Split(' ').Length;
// Save if "stop" was typed into the textbox
bool stopExisting = !txtFullName.Text.ToLower().Contains("stop");
// If text has exactly 3 words and "stop" is NOT existing
if (wordsInText == 3 && !stopExisting)
{
// Save array of splitted parts
string[] nameParts = txtFullName.Text.Split(' ');
// This is never used??
string strfirstname = nameParts[1];
// Set name-parts to labels
lblGivenEntered.Text = nameParts[0];
lblFamilyEntered.Text = nameParts[2];
}
// If text has NOT exactly 3 words and "stop" is NOT existing
else if(wordsInText != 3 && !stopExisting)
{
// If there are no 3 words, handle it here - MessageBox?
}
// If "stop" IS existing
else if(stopExisting)
{
// If text contains "stop" handle it here
// Application.Exit(); <-- if you really want to exit
}
}
You could just check, if one of the entered words is equal to the word "stop". There you need a StringComparions which ignores the case. Or you could parse the entered word into lower/upper-cases.
So if the check is true, you could just end the program with
Environment.Exit(0);
You could just check, if one of the entered words is equal to the word "stop". There you need a StringComparions which ignores the case. Or you could parse the entered word into lower/upper-cases.
So if the check is true, you could just end the program with
Environment.Exit(0);
Code:
if (strfullname.ToLowerInvariant().Contains("stop"))
{
Environment.Exit(0);
}

C# WinForm + Barcode Scanner input, TextChanged Error

UPDATE: SOLUTION AT END
I have a Winform, label1 will display some info returned from a SQL Search using the input (MemberID) received from barcode scanner via txtBoxCatchScanner.
Scenario is people swiping their MemberID Cards under the scanner as they pass through reception and the Winform automatically doing a Search on that MemberID and returning their info including for example "Expired Membership" etc on the receptionist's PC which has the winForm in a corner of her desktop.
I have the Below Code working fine on first swipe (eg. first person)
The number MemberID, for example 00888 comes up in the text box, ADO.NET pulls the data from SQL and displays it fine.
one thing to note maybe, the cursor is at the end of the memberID: 00888|
All good so far, THEN:
when swipe 2 (eg. next person) happens
their number (say, 00999) gets put onto the end of the first in the txtBox eg: 0088800999 so naturally when TextChanged Fires it searches for 0088800999 instead of 00999 ....
I've tried:
txtBoxCatchScanner.Clear();
and
txtBoxCatchScanner.Text = "";
and
reloading the form
at the end of my code to "refresh" the text box
but i guess they trigger the TextChanged Event
How can i refocus or ... clear the old number and cursor back to start of txtBox after the previous swipe has done its stuff...
I'm a beginner so I'm sure the code below is pretty crap....
But if anyone has time, please let me know how fix it to do what i want.
UPDATE:
Ok after much experimenting I''ve managed to get this 1/2 working now hopefully someone more experience can help me to completion! :P
if (txtBoxCatchScanner.Text.Length == 5)
{
label1.Text = txtBoxCatchScanner.Text; // just a label for testing .. shows the memmber ID
txtBoxCatchScanner.Select(0, 5);
}
SO scan 1, say 00888 , then that gets highlighted, scan 2 , say 00997 ... sweet! overwrites (not appends to) 00888 and does it's thing ... scan 2 0011289 ... DOH!!
Problem: not all barcodes are 5 digits!! they are random lengths!! Memeber ID range from 2 digit (eg. 25) to 10 digits, and would grow in the future...
Edit: Something I've discovered that is that the barcodes are read as indvidual key presses. I think this is why answer 1 below does not work and while the big probmlems:
for example with 00675 the input (?output) from the scanner is:
Down: Do
Up: Do
Down: Do
Up: Do
Down: D6
Up: D6
Down: D7
Up: D7
Down: D5
Up: D5
down: Retunn
Up: Return
other info: barcode scanner is: an Opticon OPL6845 USB
Thanks
private void txtBoxCatchScanner_TextChanged(object sender, EventArgs e)
{
Member member = new Member();
member.FirstName = "";
member.LastName = "";
//Get BarCode
//VALIDATE: Is a Number
double numTest = 0;
if (Double.TryParse(txtBoxCatchScanner.Text, out numTest))
{
//IS A NUMBER
member.MemberID = Convert.ToInt32(txtBoxCatchScanner.Text);
//SEARCH
//Search Member by MemberID (barcode)
List<Member> searchMembers = Search.SearchForMember(member);
if (searchMembers.Count == 0)
{
lblAlert.Text = "No Member Found";
}
else
{
foreach (Member mem in searchMembers)
{
lblMemberStatus.Text = mem.MemberStatus;
lblMemberName.Text = mem.FirstName + " " + mem.LastName;
lblMemberID.Text = mem.MemberID.ToString();
lblMessages.Text = mem.Notes;
if (mem.MemberStatus == "OVERDUE") // OR .. OR .. OR ...
{
lblAlert.Visible = true;
lblAlert.Text = "!! OVERDUE !!";
//PLAY SIREN aLERT SOUND
//C:\\WORKTEMP\\siren.wav
SoundPlayer simpleSound =
new SoundPlayer(#"C:\\WORKTEMP\\siren.wav");
simpleSound.Play();
}
else
{
lblAlert.Visible = true;
lblAlert.Text = mem.MemberStatus;
}
}
}
}
else
{
//IS NOT A NUMBER
lblAlert.Text = "INVALID - NOT A NUMBER";
////
//lblMemberName.Text = "";
//lblMemberID.Text = "";
//lblMemberID.Text = "";
}
SOLUTION:
The System won't let me answer my own question for another 3 hours, as I'm a newbie only 1 post, so will put here:
First thanks everyone for your help and Patience.
I Have finally figured a solition, not fully tested yet as its 2am and bed time.
following along from my updates where I had success but hit the variable length of MemberID problem. I've now overcome that with the Code below:
namespace SCAN_TESTING
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void txtBoxCatchScanner_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyValue == (char)Keys.Return)
{
e.Handled = true;
int barcodeLength = txtBoxCatchScanner.TextLength;
txtBoxCatchScanner.Select(0, barcodeLength);
//TEST
label3.Text = barcodeLength.ToString();
//TEST
label2.Text = txtBoxCatchScanner.Text;
}
}
I'll add this to my previous "real" code and test in the morning
But at this stage is doing exactly what I want! =]
Update: Tested it .. works exactly what needed:
private void txtBoxCatchScanner_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyValue == (char)Keys.Return)
{
e.Handled = true;
int barcodeLength = txtBoxCatchScanner.TextLength;
txtBoxCatchScanner.Select(0, barcodeLength);
//
//INSERT ORGINAL CODE HERE. No Changes were needed.
//
}//end of if e.KeyValue ...
}//end txtBoxCatchScanner_KeyUp
Hope that helps anyone in the future!! :)
Thanks again for the 2 very good solutions, I can see how they work, and learnt alot.
Just didn't work in my case - more likely due to myself or my error/not understanding, or scanner type.
I´m not exactly sure what the actual problem is.
txtBoxCatchScanner.Clear();
txtBoxCatchScanner.Text = "";
both trigger the "Changed" Event.
But they also clear the box. So that should be what you want to do.
You could check at the beginning if the box is actually empty, and return in case it is. Like:
if(txtBoxCatchScanner.Text == "" |txtBoxCatchScanner.Text == string.Empty)
return;
So nothing else happens, if the box is empty.
If I misunderstood your problem, please specify and I will try to help.
Regards
EDIT:
Your function should work if it looked something like this:
private void txtBoxCatchScanner_TextChanged(object sender, EventArgs e)
{
Member member = new Member();
member.FirstName = "";
member.LastName = "";
if(txtBoxCatchScanner.Text == "" | txtBoxCatchScanner.Text == string.Empty)
return; // Leave function if the box is empty
//Get BarCode
//VALIDATE: Is a Number
int numTest = 0;
if (int.TryParse(txtBoxCatchScanner.Text, out numTest))
{
//IS A NUMBER
//member.MemberID = Convert.ToInt32(txtBoxCatchScanner.Text);
member.MemberID = numTest; // you already converted to a number...
//SEARCH
//Search Member by MemberID (barcode)
List<Member> searchMembers = Search.SearchForMember(member);
if (searchMembers.Count == 0)
{
lblAlert.Text = "No Member Found";
}
else
{
foreach (Member mem in searchMembers)
{
lblMemberStatus.Text = mem.MemberStatus;
lblMemberName.Text = mem.FirstName + " " + mem.LastName;
lblMemberID.Text = mem.MemberID.ToString();
lblMessages.Text = mem.Notes;
if (mem.MemberStatus == "OVERDUE") // OR .. OR .. OR ...
{
lblAlert.Visible = true;
lblAlert.Text = "!! OVERDUE !!";
//PLAY SIREN aLERT SOUND
//C:\\WORKTEMP\\siren.wav
SoundPlayer simpleSound =
new SoundPlayer(#"C:\\WORKTEMP\\siren.wav");
simpleSound.Play();
}
else
{
lblAlert.Visible = true;
lblAlert.Text = mem.MemberStatus;
}
}
}
}
else
{
//IS NOT A NUMBER
lblAlert.Text = "INVALID - NOT A NUMBER";
////
//lblMemberName.Text = "";
//lblMemberID.Text = "";
//lblMemberID.Text = "";
}
txtBoxCatchScanner.Clear();
}
The barcode scanner you use seems to function as a HID - a keyboard emulation. Every simple barcode scanner I know (and I'm working with them on a daily basis) has the option of specifying a suffix for the scanned barcode. Change the suffix to CRLF and add a default button to your form. Scanning a barcode that ends with CRLF will then automatically "push the button".
Move the code that performs the checks from TextChanged event in to the event handler for the buttons Click event and remove the TextChanged event handler. Then, when the button is clicked, also clear the text box and set the focus back to the text box.
You should be good to go, now.
You can easily check whether the barcode scanner already has the correct suffix configured: Open up Notepad and scan some barcodes. If they all appear on separate lines, then everything's fine. Otherwise you'll need to scan some configuration barcodes from the scanner's manual.
To sum it all up, this should be the code for the button's Click event:
private void btnCheckMember_Click(object sender, EventArgs e)
{
Member member = new Member();
member.FirstName = "";
member.LastName = "";
string memberText = txtBoxCatchScanner.Text.Trim();
txtBoxCatchScanner.Text = String.Empty;
int numTest = 0;
if (String.IsNullOrEmpty(memberText) ||!Int32.TryParse(memberText, out numTest))
{
//IS NOT A NUMBER
lblAlert.Text = "INVALID - NOT A NUMBER";
return;
}
member.MemberID = numTest;
List<Member> searchMembers = Search.SearchForMember(member);
if (searchMembers.Count == 0)
{
lblAlert.Text = "No Member Found";
}
else
{
foreach (Member mem in searchMembers)
{
lblMemberStatus.Text = mem.MemberStatus;
lblMemberName.Text = mem.FirstName + " " + mem.LastName;
lblMemberID.Text = mem.MemberID.ToString();
lblMessages.Text = mem.Notes;
if (mem.MemberStatus == "OVERDUE") // OR .. OR .. OR ...
{
lblAlert.Visible = true;
lblAlert.Text = "!! OVERDUE !!";
SoundPlayer simpleSound = new SoundPlayer(#"C:\\WORKTEMP\\siren.wav");
simpleSound.Play();
}
else
{
lblAlert.Visible = true;
lblAlert.Text = mem.MemberStatus;
}
}
}
This solution avoids the following problems:
The event being triggered upon every character added/removed from the content of the text box (which is also the case when scanning a barcode: They are added one by one as if they were entered on a keyboard)
Resulting from 1. the problem that a member check is performed upon every entered character
Resulting from 2. the problem that member XYZ will never be found if there is a member XY in the database, as the check stops after finding XY
Resulting from 3. the problem that member XY will also not be found, but only member Z, because in 3. the text box is cleared and Z is the only character being entered.
The best way to clear the textBox on the next textChange event.
Insert this line
txtBoxCatchScanner.SelectAll();
at the end of TextChange function.. This will select the text, so that i can be replaced easily on the next event.

Categories

Resources