errorprovider or message box? - c#

I have a simplr windows form input(student name,studentid) to display to a listbox.
I need to check for duplicate student id in listbox before i add a value.
Can I use error provider on student id text box to do this?
any help much appreciated
please check last bit of my code below -is for/foreach loop required?
Thanks
private void txtSid_Validating(object sender, CancelEventArgs e)
{
bool can = false;
int sid = 0;
if (string.IsNullOrEmpty(txtSid.Text))
{
ep1.SetError(txtSid, "Please Enter Student ID");
can = true;
}
else if (!int.TryParse(txtSid.Text, out sid))
{
ep1.SetError(txtSid, "Student ID must be a number");
can = true;
}
else
for (int i = 0; i < lstDisplay.Items.Count; i++)
{
if (lstDisplay.Items[i].ToString().Contains(txtSid.Text))
{
ep1.SetError(txtSid, "Student ID already added");
can = true;
}
{
}
e.Cancel = can;
}

Yes, you can use Error Provider. In fact, for in-place validation such as you are doing, I tend to prefer them. I try to limit pop-up boxes, as they can be annoying to the user. Error providers, coupled with disabling a Save button, for instance, can provide a block to continuing as well as information as to why, all without annoying pop-ups.
As for checking against items already in the list box, yes, I would loop over them checking one at a time. If there are a lot of them, or if performance is highly critical, then you could implement a custom comparer for the items you add to the list box. They could also be of a custom class to facilitate the mechanics of it all.

Related

Why would this code display error even when it shouldn't?

I am sort of new to programming and I cannot get this simple looking code to work
What I am trying to do is make a login system that works on an array so its easier to edit and add new people onto the list.
string[] UserCodes = { "admin", "testcode" }; //these are the arrays
string[] UserWords = { "123", "testword" };
public void Button_Clicked(object sender, EventArgs e)
{
for (int i = 0; i < UserCodes.Length; i++)
if (UserCode.Text.Equals(UserCodes[i]) && UserWord.Text.Equals(UserWords[i]))
{
Navigation.PushAsync(new HomePage());
}
for (int i = 0; i < UserCodes.Length; i++)
if (UserCode.Text != (UserCodes[i]) || UserWord.Text !=(UserWords[i]))
{
DisplayAlert("Something Went Wrong", "Incorrect Password or Username", "Try Again");
}
} // And this is the "main" code
I believe the main problem arises from the second part, where it displays an error, because if I don't enter the password correctly it works as it should but if I do enter correctly It sends me to the home page while still displaying the error. I have tried using else if, and i tried to use (!command.Equals(Array[i])). I am extremely confused as to why its acting this way.
Step through this code in the debugger. If you type in a correct UserCode and UserWord you will call Navigation.PushAsync(new HomePage())... and then keep going.
You next check if any UserWord or UserCode is not what you typed, and it will be, then show your error message.
You probably want to call return after Navigation.PushAsync(new HomePage()), or skip over the second for statement.
It feels like a code smell to me when you have one loop checking for a condition followed by an entirely different loop for when that condition fails. As #Corvus noted, you should return once you've made a match, and then you defer the error message after all looping is complete:
public void Button_Clicked(object sender, EventArgs e)
{
for (int i = 0; i < UserCodes.Length; i++)
{
if (UserCode.Text.Equals(UserCodes[i]) && UserWord.Text.Equals(UserWords[i]))
{
Navigation.PushAsync(new HomePage());
return; // thanks to #Corvus
}
}
DisplayAlert("Something Went Wrong", "Incorrect Password or Username", "Try Again");
}
That said, there are improvements you could make but did not ask about. Usually, the user name is acceptable regardless of case, but the password always must match the case. You are okay on the treatment of passwords but the user name match could be changed to ignore case.
Also, you have two arrays that must be in-sync with each other. I would suggest instead a Dictionary<string, string> where the user name is the Key and password is the Value.

checking items in a list and take a decision

I want to build a program in Windows forms where the user can create a pizza by pressing buttons.
My problem is that when the user presses an ingredient more than once, the list will just increment. I tried various methods but they don't seem to work.
I have seen a solution using a for loop checking individual items in the list however I will have to implement that 19 times which is not really efficient (once for every button)
string check = "Thin Base";
if (My_Pizza.Contains(check))
{
My_Pizza.Items.Remove("ThinBase");
My_Pizza.Items.Add("Thin Base");
}
You have "ThinBase" and "Thin Base". Not the same thing.
Also, if an item is already in the list, you don't need to do anything. Simply invert your check
string check = "Thin Base";
if (!My_Pizza.Items.Contains(check))
{
My_Pizza.Items.Add(check);
}
General idea is not to hardcode string values, but create reusable method that will do what you need: check if certain value is already in the list and if it not, add this item to list. This will help you to avoid duplicate code.
In the button event handler you simply call this method and provide string value as parameter. I'm not sure how exactly you handle button clicks, but I would suggest creating single reusable method once again and acquire string value from button.Text property.
Here is code sample for you to demonstrate the idea.
private void OnButtonClick(object sender, EventArgs e)
{
Button clickedButton = (Button) sender;
if (clickedButton != null)
{
string buttonContent = clickedButton.Text;
CheckAndAdd(buttonContent);
}
}
private void CheckAndAdd(string valueToCheck)
{
if (!My_Pizza.Items.Contains(valueToCheck))
{
My_Pizza.Items.Add(valueToCheck);
}
}

how to save an ID if the you leave the name empty?

I'm Working in this program for two days and i can not find out where I'm doing Wrong.If you could help me I really appreciate it .The Problem is when I enter 11111 for my the curator ID and leave the name Box Empty,it is not suppose to saved the curator ID .After if I put something in the box and i enter 11111 for the Curator ID it says "ID already exist please try again".
private void SaveCuratorBtn_Click(object sender, RoutedEventArgs e)
{
curator Curator = new curator();
try
{
Curator.ID = CuratorIDbox.Text;
bool sameid = false;
for (int i = 0; i < curatorlist.Count; i++)
{
if (curatorlist[i].ID == Curator.ID)
{
sameid = true;
break;
}
}
if (sameid)
MessageBox.Show("ID already exist please try again !");
else
{
curatorlist.add(Curator);
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
try
{
bool checkingname = false;
Curator.NAME = CuratorNamebox.Text;
checkingname = true;
if (checkingname)
{
MessageBox.Show("Curator Saved");
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
if (sameid)
{
MessageBox.Show("ID already exist please try again !");
}
else
{
curatorlist.add(Curator);
}
This code block is doing the following:
If the ID already exists, show an error (good!)
If the ID doesn't exist, add the whole Curator to curatorlist.
What you need is another step of validation in your code to make sure that box the name textbox and the ID textbox contain information. You could achieve this like so (replace the names of course):
else
{
if(string.IsNullOrEmpty(NameTextbox.Text) || string.IsNullOrEmpty(IdTextbox.Text)
{
MessageBox.Show("Uh oh!")
} else {
curatorlist.add(Curator);
}
Here you're checking if the textboxes are empty before even thinking about adding the Curator to curatorlist. If you need to make other checks (such as no numbers [1,2,3,4] in your NameTextbox), there are multiple ways of doing so.
You say that "when I enter 11111 for my the curator ID and leave the name Box Empty,it is not suppose to saved the curator ID"; but there is nothing in the sample code that you have provided which prevents this. That might be what you want; but you haven't coded it that way: the "curatorlist.add(Curator);" will add the curator to the collection regardless of what is in the Name box.
P.S. consider using a Dictionary, as the lookup will be faster.

How to take several numbers inputted from one textbox and add them together?

I know my question may be strange but I want to know. I'm building a program that does inventory. The user inputs numbers from their inventory list for several items in different textboxes and the program stores each input from the textboxes, when the add button is clicked. Then when the user done input numbers from the list. They click a button and it generated an excel file with all the numbers from the textboxes added up. So, far I have the final button event done and the input part done but I'm having trouble getting the inputs from one textbox to stores each one and add all of them up. I have try different method but I can't seem to get it.
My code:
int ALPTotal = 0;
int memory = 0;
private void btnSubmit_Click(object sender, EventArgs e)
{
if (txtALP.Text == "")
{
txtALP.Text = "0";
}
if (txtBookP.Text == "")
{
txtBookP.Text = "0";
}
string ALP2 = txtALP.Text;
int ALP = Convert.ToInt32(ALP2);
string BookP2 = txtBookP.Text;
int BookP = Convert.ToInt32(BookP2);
if (ALP >= 150)
{
MessageBox.Show("Please enter 150 or less", "Item Entered", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (BookP >= 150)
{
MessageBox.Show("Please enter 150 or less", "Item Entered", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
}
if (memory == 0)
{
memory = ALP;
}
else if (memory == ALP)
{
ALPTotal = memory + ALP + ALP;
MessageBox.Show("Information Added", "Added to List", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtALP.Clear();
txtBookP.Clear();
}
}
private void btnClearCells_Click(object sender, EventArgs e)
{
Excel.Application App;
Excel.Workbook workbook;
Excel.Worksheet worksheet;
App = new Excel.Application();
workbook = App.Workbooks.Add();
worksheet = (Excel.Worksheet)workbook.Worksheets.get_Item(1);
worksheet.Cells[3, 2] = ALPTotal;
worksheet.Cells[4, 2] = txtBookP.Text;
}
}
Also the program should only be able to take up to 100 inputs from each textbox. So, the user shouldn't be able to add more than 100 inputs numbers from each textbox in the program.
So, after trying many different ways and methods, I would like to know: is what I'm asking possible or is it impossible?
P.S. - If more information is needed in order to come up with an answer. Please let me know and I will post more information. Thanks
UPDATE I forget to mention earlier that the "btnSubmit_Click" is the add button method and the "btnClearCells_Click" is the Submit/Total button method. Also I added an example of what I want to do in the comments. If anyone not sure what I'm asking here
FINAL UPDATE My case is now closed. I have solve my problem and the answer can be seen below. Thanks to everyone who helped!
I found out my answer. I was reading an question from Stackoverflow.com about "How to sum any amount of user inputted numbers". All I had to do was do add an:
memory = ALP;
ALPTotal += memory;
Once I added this change to my code and tested it. My program did what I wanted.
Also thanks to finding my answer, I don't need the 100 user input limit anymore because I thought at first I needed it because I thought I had to do
ALPTotal = memory + ALP + ALP + // ALP (97 more times)
to get my wanted results but I don't. So, I would like to thank everyone who try to help me solve my problem. Thank you so much.

C# WinForms: Waiting for a button press inside an infinite loop

I'm making a simple Guess-The-Number game with a GUI. I need to wait on a loop waiting for the user to input a number in a text box and press "OK". How do I wait for an event inside a loop?
Note: I don't want message boxes. This is done in the main window, hence the need to wait for input.
EDIT: I should have explained myself better. I know that there's a loop inside the GUI. What I want is another loop inside a method. Maybe there's a better way to do this. I could code stuff inside the button's event handler, now that I think about it. Although I'd need global variables. Whataver, I'll think about it, but I hope my question is clearer now.
EDIT 2: Sorry that my question wasn't clear and the edit didn't do much help. First of all, the code is too big to be posted here. I'd probably have to post a screenshot of the GUI, so it wouldn't be of much use. Basically, I have two fields, "Max number" and "Number of allowed guesses". The user enters these two and clicks "Play". A new panel becomes available, with a text box and a "Guess" button. The user enters a guess, and the program checks to see if it's correct.
The purpose of the second infinite loop is to avoid global variables. See, each time the user clicks "Play", the game has to generate a new random number as the correct guess. If everything is done inside a method, no problem. But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
I'd also have to keep track of the remaining number of guesses outside of the method. Again, it's no big deal. I just want to avoid globals if I can.
Again, I'm sorry that my question wasn't too clear. I'm kind of tired, and I didn't feel like writing too much. If this still isn't clear, then don't bother. I'll think of something.
C# automatically loops infinitely waiting for events until your form is closed. You just need to respond to the button click event.
Jason Down's suggestion is wise, create a new GuessingGame class and add it to your project. I know you're worried about "global variables" (which everyone is taught in school never to use unless you absolutely have to), but think about your design specifications for a minute.
But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
As an alternative, store an instance of your GuessingGame class in the form. This is not a global variable! You said so yourself, the point of the game is keep track of the guesses and generate new numbers to guess every time "Play" is clicked. If you store an instance of the game in the form then open another form (e.g. a Help or About box), then the game's instance would not be available (thus, not global).
The GuessingGame object is going to look something like:
public class GuessingGame
{
private static Random _RNG = new Random();
private bool _GameRunning;
private bool _GameWon;
private int _Number;
private int _GuessesRemaining;
public int GuessesRemaining
{
get { return _GuessesRemaining; }
}
public bool GameEnded
{
get { return !_GameRunning; }
}
public bool GameWon
{
get { return _GameWon; }
}
public GuessingGame()
{
_GameRunning = false;
_GameWon = false;
}
public void StartNewGame(int numberOfGuesses, int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException("max", "Must be > 0");
if (max == int.MaxValue)
_Number = _RNG.Next();
else
_Number = _RNG.Next(0, max + 1);
_GuessesRemaining = numberOfGuesses;
_GameRunning = true;
}
public bool MakeGuess(int guess)
{
if (_GameRunning)
{
_GuessesRemaining--;
if (_GuessesRemaining <= 0)
{
_GameRunning = false;
_GameWon = false;
return false;
}
if (guess == _Number)
{
_GameWon = true;
return true;
}
else
{
return false;
}
}
else
{
throw new Exception("The game is not running. Call StartNewGame() before making a guess.");
}
}
}
This way, all the data related to the game is encapsulated within the class. Hooking up the events is easy in the codebehind of the form:
GuessingGame game = new GuessingGame();
private void btnPlay_Click(object sender, EventArgs e)
{
int numberOfGuesses = Convert.ToInt32(txtNumberOfGuesses.Text);
int max = Convert.ToInt32(txtMax.Text);
game.StartNewGame(numberOfGuesses, max);
}
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = Convert.ToInt32(txtGuess.Text);
bool correct = game.MakeGuess(guess);
if (correct)
lblWin.Visible = true;
if (game.GameEnded)
{
// disable guess button, show loss label
}
}
You should probably look for a book to actually learn windows programming.
The very basics:
1) There is already an infinite loop deep down in the windows code somewhere. Any windows program is constantly looping and scanning for input.
2) Once input is found, this loop fires off an Event.
3) Your mission, should you choose to accept it, is to write event handlers to handle those events.
you are most likely doing it wrong as it has already been pointed out, but you can use this
Application.DoEvents();
to process events when you are on an actual loop
to do it the right way
- don't use a loop
- use an edit box for the input, then a button
- implement the button onclick event
Yes, and What if I am waiting for Speech events, it could happen anytime event when a function is running, I need to handle that without recursively call a function

Categories

Resources