This question builds on the question I have asked 4 days ago complex if statement in an text changed event. I tried a lot so that the problem System.ArgumentOutOfRangeException does not occur. The problem arises because the if-statement is in a text changed event and checked 8 characters, that arise at runtime. So, not all characters are immediately available but are generated dynamically by the input of the user. This is where the problem starts, every time the text in the textbox changes, the event is fired and at the same time, the program immediately expects 8 characters and logically gives the error message System.ArgumentOutOfRangeException. To deal with this problem, I have put the hole if-statement in a try-catch block. Now it works, but is this a good practice? Are there other / better solutions? Here's an excerpt from my code:
private void txtBoxEingabe_TextChanged(object sender, EventArgs e)
{
axAcroPDF1.LoadFile("DONTEXISTS.pdf");
radioButton1.Visible = false;
radioButton2.Visible = false;
string text = txtBoxEingabe.Text.Substring(0, txtBoxEingabe.TextLength);
try
{
if (text.Substring(0, 3) == "SEH" && text.Substring(3, 1) == "M" && Convert.ToInt32(text.Substring(4, 4)) <= 2999 && (text.Substring(8, 1) == "H" || text.Substring(8, 1) == "R"))
{
radioButton1.Visible = true;
radioButton2.Visible = true;
radioButton1.Text = "1. Document";
radioButton2.Text = "2. Document";
this.radioButton1.CheckedChanged += RadioBtnChangedDC1;
this.radioButton2.CheckedChanged += RadioBtnChangedDC1;
}
}
catch
{
}
private void RadioBtnChangedDC1(object sender, EventArgs e)
{
if (radioButton1.Checked == true)
{
axAcroPDF1.LoadFile("C:\Doc1.pdf");
axAcroPDF1.gotoFirstPage();
Screensize = 100;
axAcroPDF1.setZoom(Screensize);
axAcroPDF1.setShowScrollbars(true);
axAcroPDF1.setShowToolbar(false);
}
else if (radioButton2.Checked == true)
{
axAcroPDF1.LoadFile("C:\Doc2.pdf");
axAcroPDF1.gotoFirstPage();
Screensize = 100;
axAcroPDF1.setZoom(Screensize);
axAcroPDF1.setShowScrollbars(true);
axAcroPDF1.setShowToolbar(false);
}
}
This program should be a viewer that shows hundreds of several documents.
This would be bad practice as you are not checking for the error and are instead relying on an exception.
Do this instead, and you wan't need a try/catch there.
if (txtBoxEingabe.Text.Length < 8)
return;
Related
For a program I'm making I'm required to implement a feature that allows the user 3 attempts to enter the correct Username and Password, however I'm having trouble closing the program after 3 incorrect attempts.
I understand a counter with every wrong attempt is the way to do this, but I can't for the life of me figure out why every attempt I've tried hasn't worked and resulted in the program closing after 3 wrong attempts.
I feel really stupid because I know it's right in front of me how to do it, I am still a beginner though so I was expecting to mess up on something like this
private void button1_Click(object sender, EventArgs e)
{
string stringUser = "User";
string stringPass = "Password";
int i = 0;
while (i < 3)
{
if (textBoxUsername.Text != stringUser &&
textBoxPassword.Text != stringPass)
{
i++;
}
else
{
MessageBox.Show("Test");
}
}
}
You are resetting the int i with each button click. Move it outside of the function so it doesn't get reset.
int attempts = 0;
string stringUser = "User";
string stringPass = "Password";
private void button1_Click(object sender, EventArgs e)
{
if (i >= 3){
System.Windows.Forms.Application.Exit();
}
if (textBoxUsername.Text != stringUser && textBoxPassword.Text != stringPass)
{
i++;
}
else
{
MessageBox.Show("Login Successfull");
}
}
This question already has answers here:
Why do assignment statements return a value?
(14 answers)
Closed 4 years ago.
I'm trying to display a Button called track with the text: "Start". But when I click the button I want to change the text to "Stop". Well, that's not much of a problem, but I want to change the text back in the "Start" when I press the button again. And over and over.
I already tried with an if-statement and using null, but that doesn't work. Also, the options when pressing alt+enter do not seem to work.
protected void change(object sender, EventArgs ea)
{
if (track.Text == "Track")
{
track.Text = "Track";
}
else
{
track.Text = "Stop";
}
}
Should be if (track.Text == "Start"), not single =.
You are attempting to do exactly what the errors says. Instead of if (track.Text = "Start" , it should be if (track.Text == "Start") :
protected void changetext(object sender, EventArgs e)
{
if (track.Text == "Start")
{
track.Text = "Start";
status.Text = "Je staat stil";
}
else
{
track.Text = "Stop";
status.Text = "Je bent in beweging. Ga zo door!";
}
}
After OP's edit:
protected void change(object sender, EventArgs ea)
{
if (track.Text == "Track")
{
track.Text = "Track";
}
else
{
track.Text = "Stop";
}
}
In other languages the test if (track.Text = "Start") is nearly always a typo.
C# only allows bool for comparison, to virtually eliminate the risk of a typo leading to a bug.
The only possible mistake remaining is if you have something like this :
Bool a = true;
Bool b = false;
If(a = b){
//this is true
}
Next time pay attention to that, you wan’t to compare two values, not the result of an affectation.
Its my first time working on a wpf. An existing system has to process an excel file, now the requirement is, the excel file must have five comlumns. Here is the code that has to do the processing
void InsertIDsNamesAndAddWorker_DoWork(object sender, DoWorkEventArgs e)
{
// read the excel file here
int columns = xlWorkSheet.UsedRange.Columns.Count;
if (columns == 5)
{
//do your normal processing
}
else
{
//if requirements are not met then display error message
System.Windows.MessageBox.Show("There must be five columns in this
file", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
Now this code does get into the else part, it however continues to other part which then displays an error message that says "done processing".
Here is the current code of the method that does the confirmation message
void InsertIDsNamesAndAddWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ProgressBarValue = 100;
StatusLable = "Done Processing.";
if (System.Windows.MessageBox.Show("Done Processing.", "Status", MessageBoxButton.OK, MessageBoxImage.Information) == MessageBoxResult.OK)
{
StatusLable = string.Empty;
ProgressBarValue = 0;
}
}
Now with me being new to the wpf technology, I realized that the hard-coded value of Statuslable is the one causing issues, so I went to set the ProgressBarValue to 100 if the the requirements were met and processing is done.
I also set the ProgressBarValue to zero if the colums was not equal to 5.
Here is the new code
void InsertIDsNamesAndAddWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int count = ProgressBarValue;
if (count != 100)
{
StatusLable = string.Empty;
ProgressBarValue = 0;
}
else
{
//ProgressBarValue = 100;
StatusLable = "Done Processing.";
if (System.Windows.MessageBox.Show("Done Processing.", "Status", MessageBoxButton.OK, MessageBoxImage.Information) == MessageBoxResult.OK)
{
StatusLable = string.Empty;
ProgressBarValue = 0;
}
}
}
My main question is, is this the right way though? is the any other way I can cancel the work if requirements are not met?
Use the Result prorperty of the DoWorkEventArgs instance you get passed in DoWork:
void InsertIDsNamesAndAddWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (columns == 5)
{
//do your normal processing
e.Result = true; // we're OK
}
else
{
//if requirements are not met then display error message
System.Windows.MessageBox.Show("There must be five columns in this
file", MessageBoxButton.OK, MessageBoxImage.Error);
e.Result = false; // something wrong
}
}
and then in RunWorkerCompleted check the Result value and handle accordingly.
void InsertIDsNamesAndAddWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// check if we're not cancelled or error-ed before checking the Result
result = (!e.Cancelled && e.Error == null)? (bool) e.Result: false; // what is the outcome
ProgressBarValue = 100;
if (result) {
StatusLable = "Done Processing.";
if (System.Windows.MessageBox.Show("Done Processing.", "Status", MessageBoxButton.OK, MessageBoxImage.Information) == MessageBoxResult.OK)
{
StatusLable = string.Empty;
ProgressBarValue = 0;
}
}
else
{
StatusLable = "Error in Excel sheet";
}
}
Notice that Result is of type object. You can put any instance of a type into it, even your own class, which might be needed if you want to return more fine grained details about what went wrong.
The BackgroundWorker has a property called WorkerSupportsCancellation. If this is set to true, you've got another option to cancel the execution.
Whenever something wrong happens, you can call backgroundWorker.CancelAsync(), which will set a boolean to true (which is the CancellationPending property in the BackgroundWorker object).
You can then check, during execution, if the CancellationPending is true. If so, the worker should stop.
If the worker stops, it'll launch the RunWorkerCompleted event, which will end up in the handler for the method (if any is added).
This way of cancelling can be checked at all instructions, or at the start of a for loop (as in: for (int i = 0; (i < x) && worker.CancellationPending; i++) ;)
Hope this helps!
I have a textbox which I would like to format in real time: ###-##-#### as the user types.
I have the following code:
private bool bFlag;
private void tbSSN_TextChanged(object sender, EventArgs e)
{
string str = tbSSN.Text;
if (!bFlag)
{
if (str.Length == 3 || str.Length == 6)
{
tbSSN.Text += "-";
bFlag = true;
tbSSN.SelectionStart = tbSSN.Text.Length;
}
else if (str.Length > 11)
{
tbSSN.Text = tbSSN.Text.Remove(tbSSN.Text.Length - 1);
tbSSN.SelectionStart = tbSSN.Text.Length;
}
}
else
{
bFlag = false;
}
}
The only issue is, when I hit backspace and try to enter the numbers again, it is allowing me to enter this format: #####--#### or ##-#####-##
I know I have to add a KeyPress event to ensure the above issue is resolved, but I am not sure how I would add it.
How would I code the KeyPress event?
It is a WinForm application.
Use MaskedTextBox instead of normal TextBox and define a Mask for your TextBox.
yourMaskedTextBox.Mask = "000-00-0000";
I have the following code:
private Boolean _penny = false;
public void InputTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (!_penny)
{
if (e.KeyCode == Keys.Enter & InputTextbox.Text.Contains("penny"))
{
_penny = true;
OutputTextbox.Text = "yes sir";
InputTextbox.Text = "";
}
}
}
This clears the InputTextbox so that it is ready for further input, and the commands that follow only run if the Boolean for _penny = true (ie: that the program has been ordered to listen for further commands).
At the moment, each text command ends with "_penny == false" so that the program essentially stops listening for anything.
My question is, can this Boolean value stay "true" for a length of time? ie: User says "penny", and they can ask multiple input questions for a number of minutes without having to say "penny" again.
While you could use a timer, that seems like overkill to me. All you need to do is track an expiry date/time:
private bool CurrentlyValidated
{
get
{
return DateTime.Now < _expiryTime && _validated ;
}
set
{
_validated = value ;
_expiryTime = DateTime.Now.AddMinutes(5) ;
}
}
private bool _validated ;
private DateTime _expiryTime ;
I used Nicholas Carey's solution, but slightly modified; for anyone who wants it here it is:
private DateTime _expiryTime;
public void InputTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("penny"))
{
_expiryTime = DateTime.Now.AddMinutes(1);
OutputTextbox.Text = "yes sir";
}
else if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("what time is it") && DateTime.Now < _expiryTime)
{
code runs here...
}
This sets the _expiryTime to when the word "penny" is entered into the Textbox. The user can then run any of the following commands they like for 1 minute.