I have created a button on a form for which I set a return value programatically, seen below. First, is the event handler psudocode, followed by where the dialog result is returned to.
There is a default property where one can set a button's return behavior in the user interface, i.e. the Dialog Result behavior. In my full code I cannot see anywhere this button's return is set or modified.
When testing (running in debug mode) the first time the buttonSaveSet_Click event handler is used during the execution of code the returned dialog result value is "Cancel" despite the fact that I clicked the "Set" button. However, the second time that I execute the function, by pressing the same button, the dialog result is returned as "Yes".
It seems like there is another place that the Dialog Result is being modified, and I am setting that value in the incorrect location.
psudo code
private void buttonSaveSet_Click( object sender , EventArgs e )
{
setChars = new setChars();
//set the dr to yes.
buttonSaveSet.DialogResult = DialogResult.Yes;
// set the charCount
// set the rowCount
if ( conditional statement is true )
{
//return values;
}
else
{
//return nothing;
}
Close();
}
return location:
try
{
DialogResult dResult = setValPopup.ShowDialog();
SetChars sc = setValPopup.setChars;
int max;
if ( dResult == DialogResult.Yes )
{
if ( sc.set == true )
{
//do other work
}
}
}
You should set the DialogResult property of the form to exit. Any value but DialogResult.None will force the form to close and return whatever you set as DialogResult (on the form, not on the button)
private void buttonSaveSet_Click( object sender , EventArgs e )
{
setChars = new setChars();
this.DialogResult = DialogResult.Yes;
....
// No need to call Close here
// Close();
}
The behavior you observe is due to the fact that probably the form engine examines the DialogResult property of the button before entering the click event and it is not expected to reevaluate it again at the exit from the event. Thus, your first click sets the property on the button, at the second click the property on the button is noted by the form engine and everything closes.
Based on the behaviour you are decribing. It is likely that you have set the DialogResult property set on your designer, so the first time it executes, it runs whatever value has set on the designer, and on the following executions, it runs correcly as you expect.
Look at your designer and you´ll find the problem.
Related
I have a WPF window and I'm calling it from a C++/cli code and it works fine. What I need is what's the best way to intercept user action I mean whether he click OK or Cancel. Wath I think to do is to define a Boolean property in my window and set it depends on user action. Here is my code :
MyWindowView^ window = gcnew MyWindowView();
System::Windows::Interop::WindowInteropHelper^ windowInteropHelper = gcnew System::Windows::Interop::WindowInteropHelper(window);
windowInteropHelper->Owner = (IntPtr)AfxGetMainWnd()->m_hWnd;
window->WindowStartupLocation = System::Windows::WindowStartupLocation::CenterScreen;
window->ShowDialog();
if ()
{
//some action
}
else
{
//
}
Also I want to know do I need to delete the window object ?
Window.ShowDialog returns dialog result. I can't see any reason to get this result in some way, that differs from C# or VB .NET:
System::Nullable<System::Boolean> result = window->ShowDialog();
if (result.HasValue)
{
// OK or Cancel
if (result.Value)
{
// OK clicked
}
else
{
// Cancel clicked
}
}
else
{
// dialog closed via system menu or Alt+F4
}
do I need to delete the window object ?
No, you don't. See this answer.
I have a case where a textbox is validated to make sure it is not blank. However, there are some edge cases where the value should actually be blank. A Nullable<bool> blankText = null variable is set in the constructor. I'm using this code to validate and double check if the value is actually OK to be blank by confirming this with the user:
private void text_Validating(object sender, CancelEventArgs e)
{
if (string.IsNullOrWhiteSpace(text.Text))
{
do
{
if (blankText.HasValue && !blankText.Value)
{
errorProvider.SetError(text, "Blank or whitespace!");
e.Cancel = true;
break;
}
else if (blankText.HasValue && BlankText.Value)
{
errorProvider.SetError(text, "");
e.Cancel = false;
break;
}
else
{
DialogResult result = MessageBox.Show(this, "Field is blank, or contains only whitespace.\nAre you sure you want to use a blank/whitespace?", String.Empty, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
blankText = true;
else
blankText = false;
}
}
while (true);
}
else
{
e.Cancel = false;
errorProvider.SetError(text, "");
}
}
Even if the value for blankText = null it will still set the errorProvider error and fail validation. The MessageBox dialog is never displayed. I know that according to the documentation Microsoft states the following:
Do not attempt to set focus from within the Enter, GotFocus, Leave, LostFocus, Validating, or Validated event handlers. Doing so can cause your application or the operating system to stop responding. Source
Obviously when the MessageBox is displayed the control will implicitly lose focus...so maybe that's why this strange behavior is occurring. Can anyone confirm this? Any suggestions on a better way to handle this case?
In response to #adriano-repetti comment and some additional testing I removed the prompt from the validation event. The full solution I used was to create an additional property of bool? that can be checked if blank values are allowed, disallowed, or undefined. If either disallowed or undefined the validation fails if the value is blank. If the validation fails due to a blank value and the new IsBlankValueAllowed property a prompt is displayed to ask the user to confirm this behavior. I decided to use a Property instead of data within a Tag property since it felt less 'hacked'.
Im currently facing the problem that when i try to set focus on some control (textBox), nothing happens, maybe i just overlooked something.(somewhere i found that focus is "low-level" method and that select() should be used instead, however, it doesnt work as well)
From form Login, i launch new instance of EncryptPSW form
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
EncryptPSW ePSW = new EncryptPSW();
ePSW.setOsLog(false, this);
ePSW.ShowDialog();
}
On Button(which is located on EncryptPSW form ) click event i call fill method
public void fill()
{
if (textBoxPSW.Text.Length == 8)//psw has to be 8 chars long
{
if (save)//determinating whether save or fetch of data should be done
{ login.launchSave(textBoxPSW.Text,this); }
else { login.launchOpen(textBoxPSW.Text,this); }
}
else { MessageBox.Show("The password must contain 8 characters");}
}
Which launches either save or open method from Login (my problem is just with open, since during save i dont need to do anything with Focus)
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
setFocus();
}
After all the work is done, setFocus() should be called in order to set focus and other properties.
public void setFocus()
{
textBoxDatabase.Focus();
textBoxDatabase.SelectionStart = textBoxDatabase.TextLength - 1;
textBoxDatabase.SelectionLength = 0;
}
I tried so many different ways, like:
Calling setFocus() from within EncryptPSW_FormClosed
Calling whole open process after the EncryptPSW is closed (from within EncryptPSW_FormClosed)
and many more, however i dont remember it all.
In the case of Form_Closed the weird thing is, that when i tried to show a message box from there instead of setting focus (just to see where the problem might be), it's showed before the EncryptPSW form is closed.
My only guess about this is that the instance of EncryptPSW is somehow blocking Login form and it's controls
I hoped i described my problem well enough and that it makes at least a bit of sense ;]
Thanks in advance,
Regards,
Releis
Since the textbox is in the login form, and you are opening the EcryptPWS from it as a dialog (child), your login form will not be able to set focus to anything. You will need to set focus after it is closed. You can do this:
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
using(EncryptPSW ePSW = new EncryptPSW())
{
ePSW.setOsLog(false, this);
if (ePSW.ShowDialog() == DialogResult.OK)
{
textBoxDatabase.Focus();
}
}
}
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.DialogResult = DialogResult.OK;
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
}
OK this maybe the ugliest thing I saw round this but.
using
public void setFocus()
{
textBoxDatabase.Focus();
textBoxDatabase.SelectionStart = textBoxDatabase.TextLength - 1;
textBoxDatabase.SelectionLength = 0;
}
Change your code at
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
setFocus();
}
to
delegate void settingfocus();
public void launchOpen(string psw,EncryptPSW ePSW)
{
ePSW.Close();
Encryptor.DecryptFile("loggin.bin", psw, this); //decrypting data and setting textBoxes Text property into the fetched ones
settingfocus sf = new settingfocus(setFocus);
this.BeginInvoke(sf);
}
This worked for me
(Sorry for apparently thinking insert "this" before procedure, and change line x to this was legable)
Please can someone tell me the technique that would be used, for the following scenario.
I would like to authenticate users, before I allow my code to perform another action.
I have a method that opens a new window that contains my authentication form (username and password).
private bool userLogin()
{
Window loginInterface = new Window()
{
Title = "Please Login",
Content = new login(),
Height = 282,
Width = 300,
ResizeMode = ResizeMode.NoResize,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
loginInterface.Owner = this;
loginInterface.ShowDialog();
return true;
}
I'm calling this method like so, on button click:
private void perform_action(object sender, RoutedEventArgs e)
{
if (!userLogin())
{
// Failed login, do nothing
}
else
{
// Authentication successful, perform action
delete_item();
}
}
The window opens fine, but how can I now make my method return true or false based on the what the user does on the opened form?
So when the user clicks the login button named login_button, my code already validates the credentials, but I need the 'bool' value sent back.
Can I make my first window almost wait for an action to be performed on another window and get the response back?
The Window.ShowDialog() method actually already returns a bool?. This can be set at any point from within the Window by setting (for example) this.DialogResult = true. You can then close the window and access the value from the calling code.
To close the window with a result:
this.DialogResult = true;
...and then to use that result in the calling code:
var myWindow = /*create window*/;
var result = myWindow.ShowDialog();
if (result == true)
{
//...
}
To close the login screen you can set DialogResult to true or false, and ShowDialog returns this value. For other things you can create events on the second window and subscribe to them on the first.
userLogin should return something other than true.
I would do something like this (based on the code shown):
return loginInterface.WasSuccessful; // you'd have to add this property
I am writing the following get and set for validating an input from a Text Box. Basically it is supposed to check if the user has entered all of the values.
When I leave the TextBoxes empty , it does nothing and shows a '0' in output where that variable was being used. It does however show the system generated exception and stops the execution, but I wonder why doesn't it validate the input through the properties?
Here is my code:
public double RecoDoseSize
{
get
{
return recoDoseSize;
}
set
{
if (!(value>0))
{
MessageBox.Show("Please Enter the recommended dose size for this product");
textBox8.Focus();
}
recoDoseSize = value;
}
}
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
recoDoseSize = double.Parse(textBox8.Text);
NoOfDosespUnit = TotalContentProduct/recoDoseSize;
}
You are setting recoDoseSize, the backing field, not RecoDoseSize, the property which has your code in it. Thus, your code isn't executed. You need to change the second line of your method body to
RecoDoseSize = double.Parse(textBox8.Text);
(note the capital R).
Other have given the correct answer to the question as stated. Namely that you should call the uppercased RecoDoseSize if you want to use the getter/setter.
However it is extremely bad practice to show a message box inside the setter, because it violates the Principle of Least Surprise.
When someone looks at the line RecoDoseSize = double.Parse(textBox8.Text); it is not at all obvious that this operation could cause a message box to appear.
There are occasionally exceptions where it does make sense to have a setter trigger UI changes (for instance the Visible property on controls) however the default should always be to not do this unless you are sure it will be more confusing to not do so (for instance it would be surprising if you set Visible = false however it was still visible).
Regarding your comment on how you should implement it, the checking should be done in the click handler and the property can just be an auto-property, like so:
public double RecoDoseSize { get; set; }
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
double enteredSize;
if (!double.TryParse(textBox8.Text, out enteredSize) || enteredSize <= 0)
{
MessageBox.Show("Please Enter the recommended dose size for this product");
textBox8.Focus();
return;
}
RecoDoseSize = enteredSize;
NoOfDosespUnit = TotalContentProduct / recoDoseSize;
}
You'll want to use TryParse because with Parse you'll get an error if the text isn't a valid double. What TryParse does is return true or false depending on whether it succeeded, and it populates the out parameter with the result if it's successful.
So what this does is if it either failed to parse the result, or the result is <= 0 it shows the message box. In that case it also returns from the method so the rest of it isn't executed. Alternatively the rest of the method could be in an else block in which case the return isn't needed. It's a matter a style which way is preferred.
You're never actually using the getter/setter. You are using the actual field name: recoDoseSize directly. Change it to RecoDoseSize.
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
RecoDoseSize= double.Parse(textBox8.Text);
NoOfDosespUnit = TotalContentProduct/recoDoseSize;
}
You shouldn't be handling focus in your set statement.
Also, you need to make sure that value is not null, otherwise you can't compare it to anything (greater-than, etc.).