How to show a status dialog while parent form is closing - c#

I have a WPF app that takes a while to close so I want to add a 'please wait' dialog to show up while the main form is closing. However, when I added 'formmessage.show' to my main form's closing event handler, the form displays but instead of the 'please wait' text, all i get is a white rectangle. This only seems to happen when calling this code from the closing handler. It works fine from other handlers (form click or maximize). Can anyone help? Here is my simplified code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Form1 f = new Form1();
f.Show();
System.Threading.Thread.Sleep(3000);
}
}
Form1 has a label on it which says 'please wait'.

Try out:
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Normal,
new Action(() =>
{
Form1 f = new Form1();
f.Show();
System.Threading.Thread.Sleep(3000);
}));
BTW, you can remove Thread.Sleep() because default value of the Application Shutdown mode is OnLastWindowClose so Application will be active until an user explicitly close active window, this behaviour could be changed by switching Application.ShutdownMode to OnMainWindowClose in the App.xaml file)

That would be because of the fact your creating the form in the same thread your telling to sleep, during which it's not going to respond to draw requests, try launching the form in another thread, and closing it in MainWindow's destructor.

Related

this.Close(); doesn't work in window wpf

In wpf, window I am calling window forms. Before calling that I just want to close that window. Here is my code.
public partial class MainWindow : MetroWindow
{
public MainWindow()
{
InitializeComponent();
}
private void BtnIntroClick(object sender, RoutedEventArgs e)
{
PdfReader form = new PdfReader(1);
form.ShowDialog();
this.Close();
}
}
No error, but form is not closing.
And in window form also, this.Close() in not working
public partial class PdfReader : Form
{
public PdfReader(int page_num)
{
InitializeComponent();
var executingFolder = System.AppDomain.CurrentDomain.BaseDirectory;
var dbPath = System.IO.Path.Combine(executingFolder, "BiodermaProduct.pdf");
axAcroPDF1.LoadFile(dbPath);
axAcroPDF1.setCurrentPage(page_num);
}
private void PdfReader_FormClosed(object sender, FormClosedEventArgs e)
{
this.Opacity = 0;
MainWindow w = new MainWindow();
w.ShowDialog();
}
}
It will close when you close your PdfReader form. Form.ShowDialog returns only when the form is closed. So this.Close() is not called until ShowDialog finishes.
What you can do is set this.Visibility = Visibility.Hidden before calling form.ShowDialog();
Important detail that we need to bear in mind when we deal with windows closure and other UI operation: we need to execute it in UI thread only.
This is exactly that happened in my case.
I raised an event from the server and when it happened I raised another event through custom Event Aggregator to close the second Window that is opened (without shutting down the application).
However it didn't happen without an error or visible reason. My window was still opened.
Nevertheless, when I enabled "Common Language Runtime exception" through visual studio settings:
I caught the exception: "Full Exception: System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
at System.Windows.Threading.Dispatcher.VerifyAccess()
at System.Windows.Window.Close().........."
Consequently, instead of this:
ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<ServerDisconnectedEvent>()
.Subscribe(e => Close());
Run this:
ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<ServerDisconnectedEvent>()
.Subscribe(e => Application.Current.Dispatcher.BeginInvoke(new Action(Close)));
I hope this will safe time for someone like me :)
If you read this MSDN article you'll see that ShowDialog only returns when said window is closed. This means your code is blocked on that line until the window is closed. You have to close your current window first, then ShowDialog.
private void BtnIntroClick(object sender, RoutedEventArgs e)
{
PdfReader form = new PdfReader(1);
this.Close();
form.ShowDialog();
}
Note that Show does not work in this way.
When You use Window.ShowDialog(), it calls new Window modally, meaning you cannot go to the parent form.
The Window.Show() function shows the form in a non modal form. This means that you can click on the parent form.
However, this code will close your application as MSDN says(thanks to #Empereur Aiman):
A ShutdownMode of OnMainWindowClose causes Windows Presentation
Foundation (WPF) to implicitly call Shutdown when the MainWindow
closes, even if other windows are currently open.
And you should set your ShutdownMode to OnLastWindowClose as MSDN says:
If you set ShutdownMode to OnLastWindowClose, Windows Presentation
Foundation (WPF) implicitly calls Shutdown when the last window in an
application closes, even if any currently instantiated windows are set
as the main window (see MainWindow).
Just reorder your call of ShowDialog():
PdfReader form = new PdfReader(1);
this.Close();
form.ShowDialog();
or:
PdfReader form = new PdfReader(1);
form.Show();
this.Close();
and set ShutdownMode="OnLastWindowClose" at App.xaml file of your application:
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnLastWindowClose"
>
</Application>
You code is:
PdfReader form = new PdfReader(1);
form.ShowDialog();
this.Close();
It means CLR executes modally your new PdfReader window. That is, execution of your program goes to PdfReader window. And only after closing PdfReader window, CLR executes your next row:
this.Close();
and your MainWindow() will be closed.
You need to change the order between this.Close(); & form.ShowDialog(); and it will work well
Try this code:
private void BtnIntroClick(object sender, RoutedEventArgs e)
{
PdfReader form = new PdfReader(1);
this.Close();
form.ShowDialog();
}

C# - Application continues running in the background when closing it after an another form was opened

When I click on About, a new form opens and the main form hides. I have a close button on the About button, that closes the About form, and it shows up the Main form. However, when I close the main form with the 'X' close button on top, the Main form closes, but the process is still running in the background. Everything is okay when I dont click on the About button. It kills the process.
In your Form2, you need to bring up the existing Form1 instance rather than creating a new one (that's why closing this newly created Form1 won't exit the application, as your old Form1 instance is still hiding...).
So you could get reference passed when creating aboutdialog, and show that instead when closing aboutdialog:
Form1:
private void AboutButton_Click(object sender, EventArgs e)
{
var aboutdialog = new Form2(this);
aboutdialog.Show();
this.Hide();
}
Form2:
Form1 _parentform;
public Form2(Form1 parent)
{
_parentform=parent;
InitializeComponent();
}
private void CloseButton_Click(object sender, EventArgs e)
{
_parentform.Show();
this.Close();
}
In your "AboutButton_Click" method you hide the Form1. But when closing the About dialog, you do not show back the Form1, but create a new one. The original Form1 stays hidden and prevents your application from closing.
better to use showdialog.
private void AboutButton_Click(object sender, EventArgs e)
{
var aboutdialog = new Form2();
aboutdialog.ShowDialog();
}
When form2 is closed a new instance of form1 is opened, instead of the original one. You could include a reference to Form1 inside of Form2, or use the default Ownerof a form, by showing the dialog with Form1 as its owner:
aboutdialog.Show(this);
in the about...click
and closing
private void CloseButton_Click(object sender, EventArgs e)
{
Owner.Show();
this.Close();
}

opening a window form from another form programmatically

I am making a Windows Forms application. I have a form. I want to open a new form at run time from the original form on a button click. And then close this new form (after 2,3 sec) programatically but from a thread other than gui main thread.
Can anybody guide me how to do it ?
Will the new form affect or hinder the things going on in the original main form ? (if yes than how to stop it ?)
To open from with button click please add the following code in the button event handler
var m = new Form1();
m.Show();
Here Form1 is the name of the form which you want to open.
Also to close the current form, you may use
this.close();
I would do it like this:
var form2 = new Form2();
form2.Show();
and to close current form I would use
this.Hide(); instead of
this.close();
check out this Youtube channel link for easy start-up tutorials you might find it helpful if u are a beginner
This is an old question, but answering for gathering knowledge.
We have an original form with a button to show the new form.
The code for the button click is below
private void button1_Click(object sender, EventArgs e)
{
New_Form new_Form = new New_Form();
new_Form.Show();
}
Now when click is made, New Form is shown. Since, you want to hide after 2 seconds we are adding a onload event to the new form designer
this.Load += new System.EventHandler(this.OnPageLoad);
This OnPageLoad function runs when that form is loaded
In NewForm.cs ,
public partial class New_Form : Form
{
private Timer formClosingTimer;
private void OnPageLoad(object sender, EventArgs e)
{
formClosingTimer = new Timer(); // Creating a new timer
formClosingTimer.Tick += new EventHandler(CloseForm); // Defining tick event to invoke after a time period
formClosingTimer.Interval = 2000; // Time Interval in miliseconds
formClosingTimer.Start(); // Starting a timer
}
private void CloseForm(object sender, EventArgs e)
{
formClosingTimer.Stop(); // Stoping timer. If we dont stop, function will be triggered in regular intervals
this.Close(); // Closing the current form
}
}
In this new form , a timer is used to invoke a method which closes that form.
Here is the new form which automatically closes after 2 seconds, we will be able operate on both the forms where no interference between those two forms.
For your knowledge,
form.close() will free the memory and we can never interact with that form again
form.hide() will just hide the form, where the code part can still run
For more details about timer refer this link, https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer?view=netframework-4.7.2
You just need to use Dispatcher to perform graphical operation from a thread other then UI thread. I don't think that this will affect behavior of the main form. This may help you :
Accessing UI Control from BackgroundWorker Thread
This might also help:
void ButtQuitClick(object sender, EventArgs e)
{
QuitWin form = new QuitWin();
form.Show();
}
Change ButtQuit to your button name and also change QuitWin to the name of the form that you made.
When the button is clicked it will open another window, you will need to make another form and a button on your main form for it to work.
private void btnchangerate_Click(object sender, EventArgs e)
{
this.Hide(); //current form will hide
Form1 fm = new Form1(); //another form will open
fm.Show();
}
on click btn current form will hide and new form will open

C#, How to Consistantly bring a form to the front?

I have a MainForm Class Instance,
I bring up another form like so;
InputForm MyInput= new InputForm("Enter a Number");
MyInput.ShowDialog();
I close MyInput form from within itself like this;
private void Button_Click(object sender, EventArgs e)
{
//Do things here
this.Hide();
}
Flow resumes in the MainForm and using either
this.Show();
or
this.Activate();
neither will consistantly bring the MainForm to the front.
How can I do this?
What you need to do is show your InputForm like this. This form of ShowDialog assigns the owner to your dialogbox.
DialogResult dr = MyInput.ShowDialog(this);
//test for result here
MyInput.Close();
this.Hide() appears to be hiding the main form, not the input. Because ShowDialog is a blocking method, the InputForm will need to be closed by user action, code internal to the InputForm, or by another thread.

In C# how to show a GUI from another GUI, based on the event from a class in another thread?

I am working on a DirectX based simulator.
On which I have to check for a device whether device has been plugged-in or removed from the PC.
I've managed to make classes for device arrival and removal on another thread, which raises an event from the thread itself on device arrival or removal.
The corresponding event method is being called in the main form and there:
Assume Form1 is main window and Form2 is the secondary.
Form2 form2Instance = new Form2();
I want to show another Form (Form2) keeping main Window (Form1) in behind (same as it behaves as form2Instance.ShowDialog(); in general cases.)
After a few tries I have done it by
Applicatin.Run(new Form2());, but the Form2 doesn't behave as'form2Instance.ShowDialog(); in any way.
Just giving the code if it can help in answering:
iARMdetectionThreadClass detection;
InProgram_iARMdetection iARMStatusGUI;
private void Form2_Load(object sender, EventArgs e)
{
iARMStatusGUI = new InProgram_iARMdetection();
detection = new iARMdetectionThreadClass();
detection.IniARM_device_Arrive += new iARMdetectionThreadClass.iARM_device_ArrivedEventHandler(detection_IniARM_device_Arrive);
detection.IniARM_device_Remove += new iARMdetectionThreadClass.iARM_device_RemovedEventHandler(detection_IniARM_device_Remove);
detection.startThread();
}
void detection_IniARM_device_Remove(iARM_deviceInfo senderInfo)
{
detection.StopCheckBeingRemoved();
MethodInvoker act = delegate
{
this.label_iARMStatus.Text = detection.iARM_deviceInf.iARMStatus;
};
this.label_iARMStatus.BeginInvoke(act);
Application.Run(new InProgram_iARMdetection()); //Blocking code
detection.StartCheckBeingRemoved();
}
void detection_IniARM_device_Arrive(iARM_deviceInfo senderInfo)
{
MethodInvoker act = delegate
{
this.label_iARMStatus.Text = detection.iARM_deviceInf.iARMStatus;
};
this.label_iARMStatus.BeginInvoke(act);
//detection.StopCheckArriving();
//detection.StartCheckArriving();
}
I need the code to be Blocking Code. In here:
Application.Run(new InProgram_iARMdetection()); //Blocking code
Perhaps mainform.AddOwnedForm(form2) will do what you want. It will make form2 display in front of mainform and when either one is minimized, the other is also.
You should handle the remove event on form2 rather than form1 and use the ShowDialog() method.
So when on form1 the arrival event will fire it will open up form2 like a dialog. Now when the device will be unplugged, on form2 removal event will fire where you can close the form.

Categories

Resources