Almost all applications developed contains more than one windows. Often there is a main window and a series of modal windows that are created on the fly when users click some buttons or activate a menu item. Of course this is also true for a WPF application.

When one starts programming with WPF, discovers a completely new UI design paradigm, especially if he previously have developed application only using WinForms/Win32 technologies. The same thing happened to me some years ago. Dependency Properties, Routed Events, Command Bindings, Resource Managements and so on open a new world in GUI development. All of those stuff works thanks to a powerful new concept: the Logical and Visual tree. For example a DependencyProperty is a property of a DependencyObject and, as name itself implies, is a property whose value 'depends' on the position occupied by the DependencyObject in the LogicalTree of the container Window. RoutedEvents, CommandBindings etc are all strictly related to the logical tree of a window. Of course this as very simplistic way to look at WPF but it serves to introduce the idea behind this post.

Looking at the following XAML, one can say that TextBox font family will be set to 'Tahoma' because it is a 'logical' child of the Grid which is itself child of the Window which set FontFamily property to 'Tahoma'. This means that TextBox (that is a DependencyObject) inherits its FontFamily value from the parent Window.

<Window Class="YouDev.ChildWindow_TestApp.Window1"
  Loaded="Window_Loaded" MouseDown="Window_MouseDown"
  FontFamily="Tahoma"
  Title="Window1" >
  <Grid>
    <TextBox Margin="10" Text="Sample Text"/>
  </Grid>
</Window>

TextBox uses 'Tahoma' as font family instead of its default one:

A similar example can be do easly for RoutedEvents, CommandBindings and Resource Management.

Now the problem: what happens if you create a child window of 'Window1' and put a TextBox in there? Nothing. Second TextBox uses its default font and not 'Tahoma'. This is because 'Window2' even if is a child window of 'Window1' is itself a window and defines its own LogicalTree. One usually knows about this and re-set the font to Tahoma in 'Window2easilyeasily' or better uses a style for settings custom font for all controls.

But consider the opportunity to set 'Window2' as logical child of 'Window1'. DependencyProperties on 'Window2' will work as they were created in 'Window1'. Imagine if you could handle a command in 'Window1' but is fired by a button in 'Window2' or if you could bind a property of control in 'Window2' to a datacontext defined in 'Window1'. You could use a style defined as resource in 'Window1' also in 'Window2' without put it in application level resource dictionary. Anyway I said that it is an opportunity, in the sense that a developer should decide when take advantage of it.

If you try to add 'Window2' as logical child of 'Window1', WPF complains that Window object must be the root of Logical/VisualTree. So I decided to create from scratch a ChildWindow class that implement a win32 window and host a content. Of course at the moment it is not complete and it doesn't replicate exactly the behavior of a standard Window class but it can be used to test above concepts.

I defined ChildWindow as a ContentControl because it can host only one child content and I created a method Show that user can call to create the win32 window. In addition just after window creation the ChildWindow itself is set as rootvisual. There are also some native calls to Win32 to update the position/size of the win32 window according to Left/Top and Width/Height properties of ChildWindow. Even more I had to install a hwndSource hook to spy win32 messages coming from the SO in order to maintain update WPF properties like Left/Top and Width/Height.

In definitive to create a child window, one can implement code like this:

Window2 childWindow = new Window2();
childWindow.Owner = this;
AddLogicalChild(childWindow);
childWindow.Show();

 

As you can see 'Window2' is now added as logical child of Window1 (into the form_loadeasily event handler of Window1).

This is a screenshot of the sample application I developed for this article:

Click below to download ChildWindow class code and a sample project.

YouDev.ChildWindow.rar (125.58 kb)

Currently rated 3.0 by 2 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
44 Comments