WPF: Unable to raise Window.Closing event from app module - c#

I take charge of a development of an older WPF modular application using Prism Library for WPF. In this case, entry point to the application for me is an overriden Initialize() method since I have no access to the Application.MainWindow's App class. This class along with some other helper classes is compiled to EXE file and DLL's.
Currently I'm facing to a problem that I have to catch the Window.Closing event which is not raised during closing the application. Normally this piece of code which is put into the constructor (in this specific case into Initialize() method) is working as expected
Application.Current.MainWindow.Closing += (s, e) =>
{
e.Cancel = true;
};
On the other hand, event Window.Closed is fired up without any issues.
In my opinion it's not possible to associate this event handler outside of Application.MainWindow's constructor, or do I something wrong? Please help me.

The issue was located. The OnClosing method which raises the Closing event is implemented in the shell and it looks like this
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
ViewModel.StartShutdownSequence();
}
The StartShutdownSequence() encapsulates some logic regarding handling individual modules and at the end it calls Application.Current.Shutdown() which definitely shutdown the application.

Related

App_Startup() VS OnStartup() when launching a WPF application

I am starting a new WPF project and I need lighting on the launch of the application.
I watched 2 different WPF projects to see how to begin.
The first one starts with the void App_Startup(object sender, StartupEventArgs e) method in the App.xaml.cs file, called directly from the App.xaml file (Startup="App_Startup").
The other one starts with the protected override void OnStartup(StartupEventArgs e) method in the App.xaml.cs file.
In addition of that, when I started my WPF project, the default code template starts in a third way with StartupUri="MainWindow.xaml" in the App.xaml file.
What are the differences between this three manners?
Startup is an event that is raised by the OnStartup method of the Application base class as you can see in the reference source. This is how it's implemented:
protected virtual void OnStartup(StartupEventArgs e)
{
VerifyAccess();
StartupEventHandler handler = (StartupEventHandler)Events[EVENT_STARTUP];
if (handler != null)
{
handler(this, e);
}
}
So if you override OnStartup in your App class and call base.OnStartup(e), the event will be raised and any attached event handler will be invoked. Whether you implement your logic in the event handler or directly in the overridden OnStartup is a matter of personal or application specific preference. There are no recommendations on why one should be better than the other.
When it comes to the StartupUri, it only makes sense to set this when you simply want to display a default window immediately on startup and you don't have any custom initialization logic.
In enterprise apps, it's common to have some kind of bootstrapper that sets up the application and its dependencies and create and show the main window programmatically rather than using the StartupUri property.
Startup="App_Startup" is just event handler for your application, which is started in App.xaml. It has event StartUp which you can subscribe to. If you want to have some "pre-loading" logic, this is perfect place.
If you want to have just your window shown, it is enough to specify URI (in StartUpUri) of that window, so application knows which file to load and what window to show :)
OnStartup raises event of application start (in base.OnStratUp), from the documentation:
OnStartup raises the Startup event.
A type that derives from Application may override OnStartup. The overridden method must call OnStartup in the base class if the Startup event needs to be raised.
There also can be put some pre-loading logic.
There is none recommended way, it is up to you and what you need.

c# WPF how to delay autostart of an application?

My question is how can i delay the autostart on user logon in an WPF Project. Because its necessary on this application.
I tried:
void OnStartup(StartupEventArgs e)
{
Thread.Sleep(60000);
base.OnStartup(e);
}
but it seems like the OnStartup method isnt aviable. Its always an error. So there is something i dont get.
You can always just use
public App()
{
System.Threading.Thread.Sleep(10000)
}
on the App.xaml.cs
Of as already mentioned you need to subscribe to the OnStartup event on xaml.
This answer might have what you're looking for:
I think what you really want to do is to subscribe to the Startup
event. You can do this in your XAML file
Click here to get started with WPF

How to delete file, then user closes program in WPF?

I know full path of file var temp_file = Path.Combine(_directoryName1, "temp.ini"); which need to be deleted in the end of program working. How could I do this ? As I know it is possible to realize via OncloseEvent(). In addition, I dont know exatly how user will close application via alt+f4 or via buttons.
So far, I have tried to use this code below from almost the same question How to override onclose event on WPF?
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
//do my stuff before closing
base.OnClosing(e);
}
And I have added it in App.xaml.cs but it doesn't work. VS2013 says that he don't know such method base.OnClosing(e);
Is there any mistake or another way out?
Window.Closing is for a specific Window. That's probably not what you want in any case, because the Closing event can be cancelled. Window.Closed is likely a better choice.
To run something when the program is closed -- not tying yourself to a window -- you should subscribe to the Application.Exit event instead.

How to subscribe to Application.ApplicationExit from library assembly

Is there a way to subscribe to this event or something similar so I can perform some clean up codes before objects are finalized?
The event is static so using it in a DLL doesn't cause any problem.
Do beware however that the event is only fired if your class library is actually used from a Winforms application. You can only be sure of that if you expose functionality that is only usable from a Winforms app. Like a custom control or UserControl.
Alternatives are the AppDomain events, DomainUnload and ProcessExit. Or just expecting the main app to let you know about the shutdown. Which is usually the better choice, you don't necessarily know why the app is exiting. You wouldn't want to save settings on a hard crash for example. Note how the ApplicationSettingsBase class follows that pattern as well, you have to explicitly call its Save() method.
You subscribe to this event in the same manner you would with any event.
The example on the ApplicationExit MSDN page is clear:
Application.ApplicationExit += new EventHandler(this.OnApplicationExit);
private void OnApplicationExit(object sender, EventArgs e) {
// do your cleanups
}

Windows Forms Binding: is there an event similar to DataBindingComplete, but fired when ALL bindings are completed?

I need to change a certain DataGridView's property (a DataSourceUpdateMode for one of its binding) only when ALL of its initial data bindings are completed.
I tried subscribing to the "DataBindingComplete" event, but it's fired too many times (one or more time for each binding associated to the control); what I need is a more global "AllDataBindingsComplete" event, fired when the control is ready to be displayed to the user.
As a temporary workaround, I'm using the MouseDown event (I've assumed that when the user is able to click the control, it means that the control is displayed... :) and the events I'm playing with - SelectionChanged - are fired after the MouseDown):
protected override void OnMouseDown(MouseEventArgs e)
{
Binding selectedItemsBinding = this.DataBindings["SelectedItems"];
if (selectedItemsBinding != null)
{
selectedItemsBinding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
}
base.OnMouseDown(e);
}
It works, but it smells like an ugly hack A LOT (and it's called too many times, only one time is enough for my needs).
Is there a better way?
(yes, I'm trying to adopt MVVM in a Windows Forms project, and I've added a bindable "SelectedItems" property to the DataGridView...)
What I've done at the Windows Forms form level, and may be improvised down to just the control(s) you want, is to subclass the Windows Forms baseclass into my own. Then, in its constructor, attach an extra event call to the Load() event.
So when everything else is completely loaded, only THEN will it hit my custom method (of the subclass). Since it is the bottom of the call-stack chain being attached to the event queue, I know it's last and everything else is done... Here's a snippet of the concept.
public class MyForm : Form
{
public MyForm()
{
this.Load += AfterEverythingElseLoaded;
}
private void AfterEverythingElseLoaded(object sender, EventArgs e)
{
// Do my own things here...
}
}
This concept can be applied to the Init() function too if that's more appropriate for your control... Let everything else within it get initialized(), then do you the "AfterInitialized()" function.

Categories