#203 – Window Size and Location Are Specified in Device Independent Units

The Window class has Left and Top properties that specify the location on the screen of the left and top sides of the window.  It also has Width and Height properties that specify the window’s size.  All of these are expressing in device independent units.

If the current DPI setting is 96 dpi (dots per inch), the WPF units are equivalent to pixels.  I.e. A window specified as 96 units high would appear as 1 inch high.  If the DPI setting is different, the specified WPF units are scaled by dpi/96 to get the resulting pixel value.

In other words:    # pixels = (# WPF Units) * (DPI / 96)

The reason for this is so that WPF applications will appear at roughly the same dimensions on various monitors, regardless of the pixel density.

Advertisement

#202 – An Example of Modal/Modeless Dialogs

You can see an example of both modal and modeless dialogs if you run the Windows Notepad application.

After starting the Notepad application, enter some text and then bring up the Find dialog using Edit | Find.  You’ll notice that you can switch back and forth between the Find dialog and the main Notepad window.  The Find dialog is a modeless dialog, since you can still interact with the main application.

Now close the Find dialog and open the Print dialog using File | Print.  While the Print dialog is open, you’ll notice that you can no longer interact with the main Notepad window.  The Print dialog is a modal dialog.

#201 – Showing a Modal Dialog Using ShowDialog

Rather than using the Window.Show method to show a modeless window, you can use the ShowDialog method to show the window as a modal dialog.

A modal dialog is one that appears in front of all other windows in the application and blocks interaction with all the other windows until the modal dialog is closed.

A modeless window, on the other hand, is one that you can interact with along with other windows in the application.

In the example below, we use the same child window class, but display one window as modeless (using Show) and one as modal (using ShowDialog).

        private void btnModal_Click(object sender, RoutedEventArgs e)
        {
            ChildWindow win = new ChildWindow();
            win.Title = "Modal child - " + DateTime.Now.ToLongTimeString();
            win.ShowDialog();
        }

        private void btnModeless_Click(object sender, RoutedEventArgs e)
        {
            ChildWindow win = new ChildWindow();
            win.Title = "Modeless window - " + DateTime.Now.ToLongTimeString();
            win.Show();
        }

Minimizing a modal window will also minimize its parent.

#200 – Parent/Child Relationships Between Windows

Creating a new Window object and displaying it using the Show method results in a new window in your application that is independent from any existing windows.  The new window can be minimized and maximized independently and gets its own icon on the taskbar.

Creating a new (independent) window:

    Window w = new Window();
    w.Title = DateTime.Now.ToLongTimeString();
    w.Show();

WPF supports the notion of parent/child relationships between windows.  You set up the relationship by setting the Owner property of the child window to point to the parent.

    Window w = new Window();
    w.Title = string.Format("Child #{0}", this.OwnedWindows.Count + 1);
    w.Owner = this;
    w.Show();

When you make one window the child of another:

  • When a parent is minimized, all the child windows are minimized
  • When child is minimized, parent is not minimized
  • You can interact with either window
  • The parent can’t cover a child window
  • Closing a parent closes all the child windows

#199 – An Application’s Windows Property Lists All of Its Windows

The Application class has a Windows property which is a collection of all of the windows that have been created by the current application.

Assume that we have an application with a main window that includes the following two buttons:

Whenever the user clicks on the Create New Window button, we create and show a new window.

    private void btnCreate_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        AnotherWindow win = new AnotherWindow();
        win.Title = DateTime.Now.ToLongTimeString();
        win.Show();
    }

In the Click event handler for the Where Are the Windows? button, we can iterate through all of the windows that the application created and display some information about each one.

        private void btnWhere_Click(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Window w in App.Current.Windows)
            {
                sb.AppendFormat("Window [{0}] is at ({1},{2}).\n", w.Title, w.Top, w.Left);
            }

            MessageBox.Show(sb.ToString(), "My Windows");
        }

The final result:

#198 – Creating and Showing Additional Windows

You can create and show additional Window objects at runtime–in addition to your application’s main window.

Let’s assume that we want a second type of window in our application, beyond the MainWindow class that the WPF Application wizard creates for us.  To start with, right-click in the Solution Explorer and select Add, New Item.

In the dialog, that comes up, select WPF as the template group and then Window (WPF) as the object to add.  Give the new window a name.

It will now show up in the Solution Explorer.

Finally, to create and show the new window, you just create an instance of the new class and call its Show method.  For example, we might add a Button on the main form that creates a new window whenever you click on it.

    private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        AnotherWindow win = new AnotherWindow();
        win.Show();
    }

#197 – Override Application Class Methods for Standard Events

We’ve already mentioned some of the main events that the Application class fires–e.g. Startup, Exit and SessionEnding.  We also showed how you can add event handlers to your Application-derived class to handle these events, using SessionEnding as our example.

Rather than adding an event handler for Application.SessionEnding to our class, we could have just overridden the OnSessionEnding method.  This is more appropriate in a class that already derives from Application.  Instead of specifying the handler in App.xaml and adding the handler to App.xaml.cs, we can just add code for the override to App.xaml.cs.

As an example, the override for OnSessionEnding could look something like this:

	public partial class App : Application
	{
            protected override void OnSessionEnding(SessionEndingCancelEventArgs e)
            {
                // Always call method in base class, so that the event gets raised.
                base.OnSessionEnding(e);

                // Place your own SessionEnding logic here
            }
    }

#196 – Getting a Result Back from a MessageBox

The MessageBox.Show method always returns a result, indicating which button a user clicked to dismiss the dialog box.  If you choose, you can check the result to see which button the user clicked.  The value returned will always be a member of the MessageBoxResult enumeration.

            // Not checking result
            MessageBox.Show("Hi!");

            // Always resturns MessageBoxResult.OK, since the dialog only has one button
            MessageBoxResult res = MessageBox.Show("Hello again");

In the above examples, the result didn’t really matter.  But you often want to know which of two or more buttons the user clicked.

            MessageBoxResult res = MessageBox.Show("Do you like brussel sprouts?", "Green Food", MessageBoxButton.YesNo);

            if (res == MessageBoxResult.No)
                MessageBox.Show("Me neither");
            else
                MessageBox.Show("Wow, you're a cruciferous vegetable lover!");

#195 – The Venerable MessageBox

The MessageBox class, in the System.Windows namespace, provides an easy way to display modal dialog boxes.

MessageBox provides a series of overloads of its static Show method, which you call to display a dialog box.

Here are some of the more common overloads:

Text message and a caption

            MessageBox.Show("Truffles are easy to make!", "Chocolate Alert");

.

Specify button(s) that appear on dialog

            MessageBox.Show("Do you like Belgian chocolate?", "Belgians", MessageBoxButton.YesNo);

.

Include buttons and icon

            MessageBox.Show("About to eat last truffle.  Proceed?", "Almost Out", MessageBoxButton.OKCancel, MessageBoxImage.Exclamation);

.

Buttons, icon and default result

The default result is the MessageBoxResult value that is returned if the user presses Return.

            MessageBoxResult result =
                MessageBox.Show("Have you been to Bruges?", "Lovely Spot", MessageBoxButton.YesNo, MessageBoxImage.Information, MessageBoxResult.No);

.

Options

            MessageBox.Show("In Bruges, I recommend the truffles, the belfry tower and a lovely canal trip.", "Tip", MessageBoxButton.OK,
                MessageBoxImage.Stop, MessageBoxResult.OK, MessageBoxOptions.RightAlign);

#194 – Hello WPF World, Love Blend

Let’s create a simple application using Blend.  We’ll just have a single button in a window, which will display a message when you click it.

Use Blend to create a new WPF Application project.

Find a Button on the Assets tab.

Drag it onto your main window.

Left-click to select the button.  Change its Content property to “Hello”.

The button’s content will update in the designer.

Left-click to select the button.  Click on the Events icon in the Properties panel.

Dbl-click in the text area to the right of the Click event.  A Button_Click event handler will be created and you’ll be taken to the code editor.

Erase the “TODO” comment line and add the following line:

    MessageBox.Show("I'm a Blend convert!", "About Me");

Press Ctrl-F5 to run the project.  You’ll see your main window.

Click on the Hello button to see your message.