I am creating a window object globally and display it only when it is necessary, most of the time window will be in invisible mode. I have some work to do whenever the window is visible. can any one please tell me which message should i override to put the code which is supposed to execute when a window.show method is called?
IsVisibleChanged should do what you want.
private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == true)
{
//Do what you need here
}
}
Look at the Window class documentation and also the Window lifetime cycle. Now out of this, we can conclude that you (probably) need the IsVisibleChanged event.
Related
_Changed events check it if it is changed. How can I check it from the beginning.
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
if (dateTimePicker1.Value.Month == 2)
{
pictureBox1.Visible = true;
}
else
{
pictureBox1.Visible = false;
}
}
You can call the event handler from the constructor, or sometimes better, the Load of the form:
private void MyForm_Load(object sender, EventArgs e)
{
dateTimePicker1_ValueChanged(dateTimePicker1, EventArgs.Empty);
}
There is also the Shown event called after the window first appears on the desktop.
Thus the control will be initialized as expected.
Here is the chain of calls:
Constructor : prefered place to instantiate objects and initialize UI instances.
Load : prefered place to create and initialize non designer UI objects or complete them like populating combobox or dataset.
Activated : prefered place to do things each time the form is activated and get focus.
Shown : prefered place to do things after the form is showned like open another form or show a info box.
The difference between using constructor, load or shown is mainly to have a clean code design and a smooth UI behavior.
There is no real difference between putting code in the constructor or in the load, else the reference and window handle are created.
Order of Events in Windows Forms (MS Doc)
Here's my setup: I have a TabControl with numerous tabs, and on the last tab, I have a UserControl that is added to a TabPage. This UserControl has a VisibleChanged event that is supposed to check if it is visible, and if it is displays certain information using CustomCommand().
void MyUserControl_VisibleChanged(object sender, EventArgs e)
{
//MessageBox.Show("");
UserControl us = sender as UserControl;
if (us.Visible)
{
CustomCommand();
}
//MessageBox.Show("");
}
Here is the problem: this code as-is will incorrectly think the UserControl is visible when it is not, and the CustomCommand() will run when it's not supposed to. When the commented-out MessageBox function is un-commented in either spot, the UserControl is correctly seen as not visible until, of course, the TabPage is selected. Does anyone have any idea why this would be?
Just putting it on a TabPage doesn't explain this problem. There must be other layout events involved that make the control actually visible later. The MessageBox.Show() call provides the time machine to get the Visible property checked with a delay.
The standard technique to get code to run later, the way MessageBox does, is by using the Control.BeginInvoke() method. The delegate target runs when all events have been fired and processed and the UI thread goes idle again. Like this:
void MyUserControl_VisibleChanged(object sender, EventArgs e)
{
UserControl us = sender as UserControl;
this.BeginInvoke(new Action(() => {
if (us.Visible)
{
CustomCommand();
}
});
}
Not sure if this will help you, but there is a strange, and afaik undocumented, asymmetrical behaviour with the Visible_Changed event:
It does get raised whenever the Visible property of the control changes, either to true or to false.
It also get raised whenever the Parent's Visible property changes to true and only to true!
I could not raise the event by hiding the Control by another control, or for that matter by the MessageBox, though.
I don't know how your application works, so I could not reproduce. But I did notice that indeed, when changing tabs the Visible_Changed event of a Control on the TabPage does get raised, whenever the page is selected (but not when it is unselected.) I didn't know either.
You can try to catch the other direction by either going for the SelectionIndexChanged or by hooking into the VisibleChanged event of the TabPage. This is not visible in the IDE, but it does work both ways:
tabPagexyz2.VisibleChanged += tabPagexyz_VisibleChanged;
void tabPage2_VisibleChanged(object sender, EventArgs e)
{
// do something
}
I saw wild guesses about UI race conditions being behind it, which I doubt. This would at least explain why a MessageBox would habe an influence. If you want to test, you could replace it with one the evil Applictaion.DoEvents.
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();
When WPF window appear first time, its content seem frozen. To refresh content I need to resize form, then it will be fixed. Or I hit the TAB then find a listbox -it's not visible- and click it and viola! Form updates its content again.
What do you think? Weird huh? Thanks in advance!
Edit:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.Show();
while (!AppMain.needClose)
{
System.Windows.Forms.Application.DoEvents();
DoThings();
}
}
Resizing the window would force the internals to invalidate and re-paint. You could try invalidating the form when it's loaded to force it to do the same:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.Show();
this.Invalidate();
while (!AppMain.needClose)
{
System.Windows.Forms.Application.DoEvents();
DoThings();
}
}
Unless you're doing some sort of custom message pumping though, the standard forms message pump should do that while loop for you. You might well find that because you're intercepting the window loaded event you're stopping initialisation from completing.
Calling DoEvents is a bad code smell in my experience. If you need to do something periodically, it's better to trigger it from a timer of some sort.
When your window is loaded it's already shown, why are you calling this.show() again??
I have this simple code, where when the user leaves the TextBox control, TreeView gets focused:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.treeView1.Nodes.Add("A");
this.treeView1.Nodes[0].Nodes.Add("A.A");
this.treeView1.Nodes.Add("B");
this.treeView1.Nodes[0].Nodes.Add("B.A");
}
private void textBox1_Leave(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Leave..");
this.treeView1.Focus();
}
}
If we execute this code the Leave event is fired twice:
Leave..
Leave..
But if we set focus to other control, only one Leave event is fired.
Is that a problem of the TreeView? Do you know any workaround? Should we report this to Microsoft?
Thanks,
RG
this.treeView1.Focus();
Do not use the Focus() method in an event handler that's called because of a focusing event, like Leave. If you need to prevent a focus change then use the Validating event instead. Setting e.Cancel = true stops it.
But do note that this isn't very logical to do so for a TreeView, there isn't anything the user can do to alter the state of the control. You'll trap the user. Maybe that was the intention, do make sure the user can still close the window. If not then you might need the FormClosing event to force e.Cancel back to false.
Given that there is no code there to wire up the event I'm guessing you did it from the designer which means a line of code such as
textBox1.Leave += new EventHandler(textBox1_Leave);
will have been added to the Form1.designer.cs, check this file to ensure the line doesn't exist more than once as for each time this line is run you will get an event trigger, so if you run the line 3 times the Leave event will fire 3 times when you leave the textbox!
HTH
OneShot