if a window with usercontrol is getting closed, then i should call a method in the usercontrol i.e. nothing but when usercontrol is disposed. How do i do that?
If you want to know when the garbage collector collects the UserControl use this:
~UserControl1()
{
//...
}
If you want to know when the UserControl is unloaded from its parent, use Unloaded event on the userControl
note: unlike a Window, a UserControl can't get closed.
As contols do not have a Closing/Closed event it's not that simple as overriding Dispose. Dispose may not be called under some circumstances.
You might override WndProc of the control and catch the WM_CLOSE event.
For future reference for others..
I disposed my user control that was loaded by my main window like this:
<UserControl x:Class="MyApp.Class" ... Unloaded="UserControl_Unloaded"></UserControl>
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
((MyVM)this.DataContext).Dispose();
}
Unloaded is an event available on any View.
Related
I see Windows have a Loaded event, but not a Loading event (as there is Closing and Closed events).
My expectation was that the Loaded event would occur before the window is actually displayed. However, looking at the Window Lifetime Events, it shows that the Loaded event occurs after Activated event.
I put some initialization code in the Loaded event and there is a delay after the window is displayed and before my content appears. So what is the best event handler to use for window initialization that should occur before the window is displayed?
You can override OnStartup() in App.xaml.cs, and do stuff before calling base.OnStartup(e);. I just checked and this is fired before the window's constructor.
Alternatively, set the window's visibility to Hidden in its xaml file, do your initialization in the constructor and then set the visibility to Visible once done. This won't remove the delay, but the delay is only caused by whatever your initialization code is doing, so it's unavoidable unless you go asynchronous.
Here's a simplified version of what I do (error handling removed). If the initialization takes a while, you may want to display a splash screen while you're doing your thing.
App.xaml:
<Application x:Class="MyProgram.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_StartUp" >
</Application>
App.xaml.cs:
namespace MyProgram
{
public partial class App : Application
{
private void App_StartUp(object sender, StartupEventArgs e)
{
// Create the model and MainWindow
MyModel model = CreateModel();
MainViewModel viewModel = new MainViewModel(model);
MainWindow = new MainWindow(viewModel); // Sets the DataContext
// Do things, like initialize your model
model.Initialize();
// Now show your window
MainWindow.Show();
}
}
}
I have a UserControl-derived control the displays some information fetched from a web server. I'm currently in the process of making the initialization of the control asyncronous, to improve responsiveness.
In my Load event handler, I'm creating a CancellationTokenSource, and using the associated Token in the various async calls.
I now want to ensure that if the user closes the form before the async operation completes, the operation will be cancelled. In other words, I want to call Cancel on the token.
I'm trying to figure out where to do this. If there was an Unload event that I could trap, then that would be perfect - but there isn't. In fact, I can't find any event that looks suitable.
I could trap the close event for the containing Form, but I really wanted to keep everything local to my UserControl.
Suggestions?
I suggest the Control::HandleDestroyed event. It is raised, when the underlying HWnd is destroyed (which usually happens, when the parent form is closed). To handle it in your own UserControl, you should override OnHandleDestroyed.
You have full access to the Control's properties at this moment, because it is not yet disposed of.
Another solution
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
if (parentForm != null)
{
parentForm.Closing -= parentForm_Closing;
}
parentForm = FindForm();
if (parentForm != null)
parentForm.Closing += parentForm_Closing;
}
void parentForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
parentForm.Closing -= parentForm_Closing;
parentForm = null;
//closing code
}
Why not just use the Disposed event?
When a form is closing, it will call Dispose on itself and all child controls will be disposed recursively as well.
Try this:
UserControl.Dispose();
I have an application with one main form. In the form I have one object objC of class C. The form gets from objC my control and puts it into panel. The form interacts with objC through methods calling and subscribing to objC’s events.
When I try to close the form by clicking on [X] button or by calling this.Close(), form isn’t closing. It calls handler of FormClosing. In the handler, I call objC.Dispose(). I checked, there are no exceptions generated. In objC.Dispose() I unsubscribe from all form’s event handlers. And I removed my control from panel with this code:
splitContainerMain.Panel2.SuspendLayout();
{
splitContainerMain.Panel2.Controls.Clear();
}
splitContainerMain.Panel2.ResumeLayout();
But it just won’t close. I can try to close as many times as I will, FormClosing event will be repeated, but FormClose will be never generated.
This bug is not reproduced when I don't create a control and add it to the panel. What have I done wrong?
There are few explanations for this. But one, you might have a Validating event handler that is canceling the validation. This will also cancel OnFormClosing. Fix:
void Form1_FormClosing(object sender, FormClosingEventArgs e) {
e.Cancel = false;
}
Btw, there is no point in calling Suspend/ResumeLayout, there is no layout done at form closing time. And calling Controls.Clear() does not actually dispose the controls. Rather nasty behavior that trips up a lot of programmers. Best thing to do is to do nothing, parent controls automatically dispose their children controls. And there is no point in unsubscribing events either, the form object and the objC object only reference each other, no other references exist. The garbage collector knows how to handle that.
This question seems to be releated to : Cleaning objects off a form, Where and When?
which provides two good alternatives for dealing with your object.
Either dispose of it by implementing the Form's Dispose method or
Simply ensure that the control is added to the System.ComponentModel.IContainer components property of the form. This will ensure that it's dispose method will be called when the form is disposed.
I am having a problem, when window loads, the 'selection_change' event associated with 'combo box' control is getting triggered when the window loads first time. Why its occuring and How to restrict it please?
Regards
With that code, the SelectionChanged event won't get raised. Create a new project, paste it and try it for yourself.
My guess is pretty much the same as Sekhar_ Pro's, you're populating your ComboBox from code behind, and something in there causes the SelectedItem to change.
Investigate the cmbUsers.SelectedItem in the cmbUsers_SelectionChanged event handler to see if it has some value or is null in the debugger. Also, look in the Call Stack to find what caused this event to be raised.
Example code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
cmbUsers.Items.Add(new ComboBoxItem { Content = "Test" });
cmbUsers.SelectedIndex = 0;
}
private void cmbUsers_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cmbUsers.SelectedItem != null)
{
MessageBox.Show(cmbUsers.SelectedItem.ToString());
}
}
}
The Call Stack looks like this for me in the event handler
This is not a normal Behavior, some where you must be doing something like setting SelectedItem, etc which in turn is triggering the event. Check thorough your form's life-cycle events and see if you are doing something like this, may be in Load or Activate event or somewhere in the Constructors.
I have window A and window B. In window A I call B.show(). I want to know in window B which method is called and I want to load data when B is showing up. thanks,
You can always listen to the "Loaded" event:
BWindow.Loaded += new RoutedEventHandler(BWindow_Loaded);
void BWindow_Loaded(object sender, RoutedEventArgs e)
{
//Your Code here
}
Then in your AWindow call
BWindow.Show();
You may be surprized, but when you call B.Show(), the method which is called is Show().
About loading additional data after window B is shown, you may subscribe to its Loaded event (see answer of #masenkablast). The better idea would be perhaps to derive from Window class and bind to the needed data in XAML. (You are using WPF, not WinForms, I suppose.)
I think it is better to have a Property which is set before B.Show() is called. This way you can always get the method which invokes the show method based on the property.