Geeks With Blogs
Ilya Verbitskiy Thoughts and links about computer programming

WPF is full of surprises. It makes complicated tasks easier, but at the same time overcomplicates easy  task as well. A good example of such overcomplicated things is how to run code when you’re sure that window rendering is completed. Window Loaded event does not always work, because controls might be still rendered. I had this issue working with Infragistics XamDockManager. It continued rendering widgets even when the Window Loaded event had been raised. Unfortunately there is not any “official” solution for this problem.

But there is a trick. You can execute your code asynchronously using Dispatcher class.

 

Dispatcher.BeginInvoke(new Action(() => Trace.WriteLine("DONE!", "Rendering")), DispatcherPriority.ContextIdle, null);

 

This code should be added to your Window Loaded event handler. It is executed when all controls inside your window are rendered.

I created a small application to prove this idea. The application has one window with a few buttons. Each button logs when it has changed its actual size. It also logs when Window Loaded event is raised, and, finally, when rendering is completed.

Window’s layout is straightforward.

 

   1:  <Window x:Class="OnRendered.MainWindow"
   2:          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:          Title="Run the code when window rendering is completed." Height="350" Width="525"
   5:          Loaded="OnWindowLoaded">
   6:      <Window.Resources>
   7:          <Style TargetType="{x:Type Button}">
   8:              <Setter Property="Padding" Value="7" />
   9:              <Setter Property="Margin" Value="5" />
  10:              <Setter Property="HorizontalAlignment" Value="Center" />
  11:              <Setter Property="VerticalAlignment" Value="Center" />
  12:          </Style>
  13:      </Window.Resources>
  14:      <StackPanel>
  15:          <Button x:Name="Button1" Content="Button 1" SizeChanged="OnSizeChanged" />
  16:          <Button x:Name="Button2" Content="Button 2" SizeChanged="OnSizeChanged" />
  17:          <Button x:Name="Button3" Content="Button 3" SizeChanged="OnSizeChanged" />
  18:          <Button x:Name="Button4" Content="Button 4" SizeChanged="OnSizeChanged" />
  19:          <Button x:Name="Button5" Content="Button 5" SizeChanged="OnSizeChanged" />
  20:      </StackPanel>
  21:  </Window>

 

SizeChanged event handler simply traces that the event has happened.

 

   1:  private void OnSizeChanged(object sender, SizeChangedEventArgs e)
   2:  {
   3:      Button button = (Button)sender;
   4:      Trace.WriteLine("Size has been changed", button.Name);
   5:  }

 

Window Loaded event handler is slightly more interesting. First it scheduler the code to be executed using Dispatcher class, and then logs the event.

 

   1:  private void OnWindowLoaded(object sender, RoutedEventArgs e)
   2:  {
   3:      Dispatcher.BeginInvoke(new Action(() => Trace.WriteLine("DONE!", "Rendering")), DispatcherPriority.ContextIdle, null);
   4:      Trace.WriteLine("Loaded", "Window");
   5:  }

 

As the result I had seen these trace messages.

 

   1:  Button5: Size has been changed
   2:  Button4: Size has been changed
   3:  Button3: Size has been changed
   4:  Button2: Size has been changed
   5:  Button1: Size has been changed
   6:  Window: Loaded
   7:  Rendering: DONE!

 

You can find the solution in GitHub.

Posted on Tuesday, October 16, 2012 9:34 PM WPF | Back to top


Comments on this post: WPF: Running code when Window rendering is completed

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
This is really a very useful trick and help me solve the problem I've encountered.
Left by Scott Chiu on Oct 24, 2013 10:19 PM

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
Thanks a lot. you save me a lot of time
Left by hossein narimani rad on Feb 19, 2014 9:19 AM

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
very nice trick . Thanks a lot
Left by Indu on Mar 20, 2015 7:36 AM

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
I was breaking my head over why the 'Loaded' event for a control i wanted to measure popped up at the wrong time - This little tidbit just solved my issue and saved me a lot more headaches. Thanks for sharing!
Left by Ran Sagy on Mar 26, 2015 10:04 PM

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
thanks. that helped :)
Left by young padawan on Apr 19, 2015 3:49 PM

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
Even Activated event of window can be used.
It use to call when window is completely rendered.
Left by Alok Aswal on Apr 29, 2015 4:18 PM

# re: WPF: Running code when Window rendering is completed
Requesting Gravatar...
Great trick, I'm not real familiar with BeginInvoke used this way, but how can you be sure that the Action only happens once? I did some testing, and I tried deactivating and reactivating the window, and fortunately the Action did not get stroked. It only got invoked after the controls were loaded, as it is supposed to.

I guess I'm asking, is this technique similar to an Event, and therefore it could get stroked again after the window is loaded if the necessary conditions are present?
Left by Mike Roth on Aug 28, 2015 2:04 PM

Your comment:
 (will show your gravatar)


Copyright © Ilya Verbitskiy | Powered by: GeeksWithBlogs.net | Join free