I'm trying to make an Option dialog in Visual Studio. I hid the default ControlBox and made a close button. The dialog work, but the close button isn't. Here's the code:
public static class dialog
{
static Form gotoBox = new Form();
public static void showDialog()
{
Button closeButton = new Button() { Text = "Close" };
gotoBox.Controls.Add(closeButton);
gotoBox.ControlBox = false;
gotoBox.ShowDialog();
closeButton.Click += new System.EventHandler(gotoBox_close);
}
static void gotoBox_close(object sender, EventArgs e)
{
gotoBox.Close();
}
}
When I click the button, nothing happen. So what did I do wrong?
gotoBox.ShowDialog(); //This line shows the dialog
//The rest doesn't execute until ShowDialog returns
closeButton.Click += new System.EventHandler(gotoBox_close);
You need to move the event registration before the show dialog or else it will not have any effect until dialog is closed
Related
I am working on a WinForms Desktop application in C# .NET. The target framework is .NET Framework 4.8. When the application is started, the main form is displayed with several buttons. Each button hides the main form when clicked and opens another form that displays data with which the user interacts. The main form is the owner of the new form.One button opens a form that presents a list of files from a network share folder in a data grid view. The user selects a row in the data grid and clicks a button to import the information in the file to various tables in a SQL Server database. When the import is complete, the selected row is removed from the data grid. When the user closes this form, there is code in the Form Closed event to show the owner. This all works well.My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.I realize I can place the code to disable the button and change button text in the VisibleChanged event. But, I only want the code to run after the owned form's closed event shows the owner form. How do I enclose the code in the main form's VisibleChanged event to disable the file import button only after the owned form is closed. Or, is it possible to edit the properties of the button on the owner form in the Form Closed event prior to the Owner.Show();I found a similar question WinForm Form Closed Event. But when I follow the suggestion
private void LoadChildForm_Click(object sender, EventArgs e)
{
ChildForm form = new ChildForm();
form.FormClosed += new FormClosedEventHandler(ChildFormClosed);
form.Show();
}
substituting my names
private void btnImportHFR_Click(object sender, EventArgs e)
{
Form form = new frmHFRFiles();
form.FormClosed += new FormClosedEventHandler(frmHFRFiles_FormClosed);
form.Show(this);
Hide();
}
Visual Studio flags frmHFRFiles_FormClosed as an error for the name does not exist in the current context.
ChildForm form = new ChildForm(this);
Then in ChildForm constructor:
MainForm m_MainForm;
Public ChildForm (MainForm mainForm)
{
m_MainForm = mainForm;
}
Then in closing event:
m_MainForm.button1.Enabled = false;
Ensure button1 is public
Here is what I did. I created a boolean variable in the main form and set the initial value to false.
private bool updateButtons = false;
The main form's constructor executes the search for files in the network folder.
public frmMainMenu()
{
InitializeComponent();
Shared.FilesForImport = GetHFRFiles();
}
The form's load event calls the EnableButtons() method
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
The main form's visible changed event fires after the form load event. The network folder is not searched again because the updateButtons value is set to false.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
In the button click event, the updateButtons value is set to true after the main form is hidden.
private void btnImportHFR_Click(object sender, EventArgs e)
{
frmHFRFiles form = new frmHFRFiles();
form.Show(this);
Hide();
updateButtons = true;
}
The child form's closed event calls the Owner.Show() method
private void frmHFRFiles_FormClosed(object sender, FormClosedEventArgs e)
{
Owner.Show();
}
This causes the main form's visible changed event to fire. Only this time the EnableButtons() method will run because the updateButtons value is true.
private void frmMainMenu_VisibleChanged(object sender, EventArgs e)
{
if(updateButtons)
{
EnableButtons();
}
}
public void EnableButtons()
{
btnImportHFR.Enabled = Convert.ToBoolean(Shared.FilesForImport.Count);
btnImportHFR.Text = btnImportHFR.Enabled ? "Find Available HFR" : "No HFR For Import";
btnGetFacilityStatus.Enabled = Shared.sqlWrap.GetDataForFacStat(Shared.DsFacStat);
updateButtons = false;
}
Finally, the EnableButtons() method sets the updateButtons value to false.
It seems rudimentary to me, but it works. Thank you everyone for your feedback.
My problem is that when the main form is unhidden, I need to disable the button that opens the form to list files to import if there are not any files in the network share folder to be imported. There is also a line of code to change the button's text property informing the user there are not any files to import.
So your main form has a button X. If this button is clicked a method is called. This method will first hide the form, then show the subform until the subform is closed. The method should disable button X, change the button's text and unhide the form.
To make this flexible, we won't do everything in one procedure, we make several procedures with the intention of the procedure: "Inform operator there are no files to import" "Disable opening the subform", and of course their counterparts "Enable opening the subform", "Inform operator there are files to import"
TODO: invent proper method names
private void ShowNoFilesToImport()
{
this.buttonX.Text = ...;
}
private void DisableOpeningSubForm()
{
this.buttonX.Text.Enabled = false;
}
The advantage of this, is that if you later want to change the way that you want to inform the operator, for instance if you want to use an information field at the bottom of you screen, you will only have to change this in one place.
Furthermore, you can reuse the procedures, for instance you can add a menu item that will do the same as button X, this menu item can call the same methods
private void PerformActionsButtonX() // TODO: invent proper name
{
// Hide this form, and show the Subform until it is closed
this.Visible = false;
using (var dlg = new SubForm())
{
// if needed, set properties of the subForm:
dlg.Text = ...
dlg.Position = ...
// show the form until it is closed
var dlgResult = dlg.ShowDialog();
this.ProcessDlgResult(dlgResult, dlg);
}
// Show that there are no files to Import and disable OpeningSubform
this.ShowNoFilesToImport();
this.DisableOpeningSubform();
// Finally: show this form:
this.Visible = true;
}
And of course call this method when ButtonX or menu item Y are clicked:
private void OnButtonX_Clicked(object sender, ...)
{
this.PerformActionsButtonX();
}
private void OnMenyItemYClicked(object sender, ...)
{
this.PerformActionsButtonX();
}
I have an application in which I need to make sure the form opened by click on a button on a user control using ShowDialog(), will be closed and disposed when I dispose the user control.
I'm calling userControl.Dispose() in my main form through a timer.
Is there a way I can do that ?
Thanks...
Here is more details about the flow of the forms:
The MainForm of my application is creating a UserControl which has a Button. Than when the user clicks on the button of the user control, it shows a model form using ShowDialog.
Meanwhile, and after a few minutes, a timer in the main form replaces the existing user control with another instance of the user control. The main form calls the Dispose method of the previous user control, and the shows the new on.
But the problem is the modal dialog is still open on screen, blocking the main form. I want to close it, and the code placed after the ShowDialog method should not be executed.
Short answer
You can subscribe Disposed event of your UserControl and close the form which it shows. Regarding to the comments under the question, it looks like you have a UserControl containing a Button and in Click event of the button, you show a Form using ShowDialog().
To close and dispose the form, you need to subscribe Disposed event of your UserControl before showing the form as dialog.
More details
If you want to decide to run some logic depending to the dialog result of the form, you can check the dialog result and if it's OK, run the custom logic which you need.
To enhance the flow a bit, you can define some events and properties in your user control and handle them in the main form:
OKSelected event, and you can raise it immediately after closing the dialog if the dialog result is OK. It will let you to handle this event in the main form, for example to stop the timer if the user clicked OK in dialog.
ProcessingFinished, and you can raise it after you finished some processing after closing the dialog when the dialog result is OK. You can handle this in main form, for example to start the timer again.
You can define some properties in case you want to communicate some values with the main form.
Here is an example of the code in main form:
MyUserControl uc = null;
private void timer1_Tick(object sender, EventArgs e)
{
if (!(uc == null || uc.IsDisposed || uc.Disposing))
{
this.Controls.Remove(uc);
uc.Dispose();
}
uc = new MyUserControl();
this.Controls.Add(uc);
uc.OKSelected += (obj, args) => { timer1.Stop(); };
uc.ProcessingFinished += (obj, args) =>
{
MessageBox.Show(uc.Info);
timer1.Start();
};
}
And here is an example of the user control:
public partial class MyUserControl : UserControl
{
public MyUserControl() { InitializeComponent(); }
public EventHandler OKSelected;
public EventHandler ProcessingFinished;
public string Info { get; private set; }
private void button1_Click(object sender, EventArgs e)
{
using (var f = new Form()) {
var button = new Button() { Text = "OK" };
f.Controls.Add(button);
button.DialogResult = DialogResult.OK;
this.Disposed += (obj, args) => {
if (!(f.IsDisposed || f.Disposing)) {
f.Close(); f.Dispose();
}
};
if (f.ShowDialog() == DialogResult.OK) {
//If you need, raise the OKSelected event
//So you can handle it in the main form, for example to stop timer
OKSelected?.Invoke(this, EventArgs.Empty);
//
//Do whatever you need to do after user closed the dialog by OK
//
//If you need, raise the ProcessingFinished event
//So you can handle it in the main form, for example to start timer
//You can also set some properties to share information with main form
Info = "something";
ProcessingFinished?.Invoke(this, EventArgs.Empty);
}
}
}
}
Can you modify the forms that you want to close automatically? If so, try adding the following to each form:
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
if (this.Owner != null)
this.Owner.HandleDestroyed += onOwnerHandleDestroyed;
}
void onOwnerHandleDestroyed(object sender, EventArgs e)
{
this.Close();
}
NOTE: You are already using Dispose() to close the main form, so this should work. If, however, you used Close() to close the main form, then it wouldn't work because Close() doesn't close a form if it is the parent of any modal dialog.
I have a button click event which will pop up a form. How do I check if an existing form is already present before creating one and showing it?
here is my code
private void Button_Click(object sender, RoutedEventArgs e)
{
Wizard wizard = new Wizard();
if (wizard.IsVisible)
{
}
else
{
wizard.Show();
}
}
the code here does not work as a new pop up wizard (form) is created everytime i click on the button from another window.
Either use ShowDialog and make it modal
Or use the reference reference to wizard or a bool flag to make the check. Make sure if you use a reference to set it null afterwards
bool isOpen;
...
public void click()
{
if (!isOpen)
{
// do something
wizard = new Wizard();
wizard.Closing += (sender, args) =>
{
isOpen = false;
};
isOpen = true;
wizard.Show();
}
...
Or as noted in comments. Set the button Enabled property false to protect from further hits
Enabled = false;
If the user clicks on a button, a dialog shows up, asking to input a string, and there's an 'OK' button on the same dialog, when the user presses that, the dialog should close. That's at least the plan, the problem is: after adding the eventhandler to the OK button, my application freezes, when the user would open the dialog.
addNewFamButton = FindViewById<Button>(Resource.Id.newFamilyButton);
addNewFamButton.Click += (sender, e) => {
Dialog dialog = new Dialog(this);
dialog.SetContentView(Resource.Layout.addNewFamily);
dialog.SetTitle("Add new family to the list");
dialog.Show();
// Problem starts here:
Button saveNewFamily = FindViewById<Button>(Resource.Id.dialogButtonOK);
saveNewFamily.Click += (object o, EventArgs ea) => { dialog.Dispose(); };
};
I tried it with dialog.Cancel() too, but I got the same results. If I remove the last two lines, the dialog works, but obviously won't close.
FIXED: Thanks to user370305 for the simple solution:
Button saveNewFamily = dialog.FindViewById<Button>(Resource.Id.dialogButtonOK);
Your OK button is part of Dialog view, so you have to find that view using your dialog object reference, something like, (I am not familiar with xamarin but this one gives you hint)
Change your line,
// Problem starts here:
Button saveNewFamily = FindViewById<Button>(Resource.Id.dialogButtonOK);
with
Button saveNewFamily = dialog.FindViewById<Button>(Resource.Id.dialogButtonOK);
try this
// create an EditText for the dialog
final EditText enteredText = new EditText(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title of the dialog");
builder.setView(enteredText);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int id)
{
// perform any operation you want
enteredText.getText().toString());// get the text
// other operations
dialog.cancel(); // close the dialog
}
});
builder.create().show();
I am new to programming. I am using window form in VisualStudio C#.
My problem is after clicking the first button in my Window Form, It opens the browser and go to Url that I want to login and after that when I click the Second button on my Window Form, it doesn't run the second block of codes. I don't get any error message.
Can anyone help me because I am totally a beginner. Thank you so much in advance!
public partial class Form1 : Form
{
IWebDriver driver = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
driver = new FirefoxDriver();
driver.Url = "https://accounts.google.com/ServiceLogin";
driver.Manage().Window.Maximize();
}
private void button2_Click(object sender, EventArgs e)
{
driver.Url = "https://accounts.google.com/ServiceLogin";
var email = driver.FindElement(By.Id("Email"));
email.SendKeys("-------------");
var password = driver.FindElement(By.Id("Passwd"));
password.SendKeys("---------");
password.FindElement(By.Id("signIn"));
Add button2.Click += button2_Click; to your Form constructor, right after InitializeComponent();. This line adds the event handler button2_Click to the event Button.Click of button2.
Normally, this kind of stuff does the designer for you. If you prefer this way, go to the preview page of your Form, then to the property manager, click the lightning "events" and double click your desired event, in this case Click. Having this done, the method body for the button2 click event handler will be generated.