Home Business & Other Windows Presentation Foundation Development Cookbook

Windows Presentation Foundation Development Cookbook

books-svg-icon Book
eBook $51.99 $35.99
Print $65.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $51.99 $35.99
Print $65.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    WPF Fundamentals
About this book
Windows Presentation Foundation (WPF) is Microsoft's development tool for building rich Windows client user experiences that incorporate UIs, media, and documents. With the updates in .NET 4.7, Visual Studio 2017, C# 7, and .NET Standard 2.0, WPF has taken giant strides and is now easier than ever for developers to use. If you want to get an in-depth view of WPF mechanics and capabilities, then this book is for you. The book begins by teaching you about the fundamentals of WPF and then quickly shows you the standard controls and the layout options. It teaches you about data bindings and how to utilize resources and the MVVM pattern to maintain a clean and reusable structure in your code. After this, you will explore the animation capabilities of WPF and see how they integrate with other mechanisms. Towards the end of the book, you will learn about WCF services and explore WPF's support for debugging and asynchronous operations. By the end of the book, you will have a deep understanding of WPF and will know how to build resilient applications.
Publication date:
February 2018
Publisher
Packt
Pages
524
ISBN
9781788399807

 
WPF Fundamentals

In this chapter, we will cover the following recipes:

  • Installing WPF Workload with Visual Studio 2017
  • Creating WPF applications
  • Creating and navigating from one window to another
  • Creating and navigating from one page to another
  • Creating a dialog box
  • Creating ownership between windows
  • Creating a single instance application
  • Passing arguments to WPF applications
  • Handling unhandled exceptions
 

Introduction

The Windows Presentation Foundation (WPF) provides developers with a unified programming model to build dynamic, data-driven desktop applications for Windows. It was first released in 2006 along with .NET 3.0. It is part of the .NET Framework itself.

WPF is a graphical subsystem, for rendering rich user interfaces (UIs), and is a resolution-independent framework that uses a vector-based rendering engine in the Extensible Application Markup Language (XAML) to create stunning user interfaces. It supports a broad set of features that includes application models, controls, layouts, graphics, resources, security, and more.

The runtime libraries for it to execute have been included with Windows since Windows Vista and Windows Server 2008. If you are using Windows XP with SP2/SP3 and Windows Server 2003, you can optionally install the necessary libraries.

To begin learning the different recipes of WPF, you should have a clear understanding of the basic foundations. In this chapter, we will start with the architecture and syntaxes, and will guide you in creating a building block.

 

The WPF Architecture

WPF uses a layered architecture that includes managed, unmanaged, and the core APIs in five different layers called Presentation Framework, Presentation Core, Common Language Runtime, Media Integration Library, and OS Core. The programming model is exposed through the managed code.

In the following diagram, you can see a clear picture of the architecture:

 

Presentation Framework

The Presentation Framework, which is part of presentationframework.dll, provides the basic required components (such as controls, layouts, graphics, media, styles, templates, animations, and more) to start building the UIs of your WPF applications. It is part of the managed layer.

 

Presentation Core

The Presentation Core layer, part of presentationcore.dll, provides you with the wrapper around the Media Integration Library (MIL). It present you with the public interfaces to access the MIL Core and the Visual System to develop the Visual Tree. It contains visual elements and rendering instructions to build applications for Windows using the XAML tools. This is also part of the managed code.

 

Common Language Runtime

Common Language Runtime, commonly known as the CLR and part of the managed layer, provides you with several features to build robust applications covering common type system (CTS), error handling, memory management, and more.

 

Media Integration Library

The Media Integration Library (MIL), which resides in milcore.dll, is part of the unmanaged layer used to display all graphics rendered through the DirectX engine. It provides you with basic support for 2D and 3D surfaces, and allows you to access the unmanaged components to enable tight integrations with DirectX. It also enables you to gain performance while rendering instructions from the Visual System to the Common Language Runtime (CLR).

 

OS Core

Just after the MIL, the next layer is the OS Core, which provides you with access to the low-level APIs to handle the core components of the operating system. This layer includes Kernel, User32, DirectX, GDI, and device drivers.

 

Types of WPF applications

Though WPF is mainly used for desktop applications, you can also create web-based applications. Thus, WPF applications can be of two types:

  • Desktop-based executables (EXE)
  • Web-based applications (XBAP)

The desktop applications are the normal .exe executables, which you normally run on any of your Windows-based systems, whereas the web-based applications are the .xbap files that can be deployed in web servers and can run inside any supported browser. The .NET Framework is mandatory to run any of these application types.

When you run a WPF application, it starts in two threads. The UI thread uses the System.Threading.DispatcherObject to create the messaging system and that maintains the UI operations queue. Just like the Win32 message pumping, it performs the UI operation based on the priority set for it.

The other thread is the background thread, which is used to handle the rendering engine being managed by WPF. It picks up a copy of the visual tree and performs actions to show the visual components in the Direct3D surface. Then it calls the UI elements to determine the size and arranges the child elements by their parents.

 

The XAML overview

XAML stands for Extensible Application Markup Language. It is an XML-based markup language that is used to declaratively create the UI of any XAML-based application, such as Windows Platform Foundation (WPF), Universal Windows Platform (UWP), and Xamarin.Forms. You can create visible UI elements in a declarative XAML syntax to design the rich UI and then write the code behind to perform a runtime logic.

Microsoft recently introduced XAML Standards, which is a specification that defines a standard XAML vocabulary, which will allow the supported frameworks to share common XAML-based UI definitions.

You can learn more about this specification by visiting GitHub here:
http://aka.ms/xamlstandard.

Though it is not mandatory to use the XAML markup to create a UI, it has been widely accepted as the smart option for the creation of the entire application's UI, as it makes things easier to create. You can create the UI by writing C# or VB.NET code too, but that makes it more difficult and tougher to maintain. Also, that makes it difficult for the designers to work independently.

Designing an application UI using XAML is as easy as writing an XML node with a few optional attributes. Attributes are used to set additional styles, behaviors, and properties. To create a simple button in the UI, you can just write <Button /> in your XAML file. Similarly, you can just write <TextBox /> to create a user-input box.

Additionally, you can add more details to the controls. For example, to add a label to a button, use its Content property, and to set its dimension, use the Height and Width property, as shown in the following code:

    <Button Content="Click Here" /> 
    <Button Height="36" Width="120" /> 

In general, when you add XAML pages to your WPF application project, it compiles along with the project and produces a binary file in what is known as Binary Application Markup Language (BAML). The final output of the project (that is, the assembly file) contains this BAML file as a resource. When the application loads into the memory, the BAML is then parsed at runtime.

You can also load an XAML into memory and directly render it on the UI. But, in this case, if it has any XAML syntax errors, it will throw those in runtime. If you compare the performance with the first process, the latter is slower, as it renders the entire XAML syntax onto UI.

Here's a flow diagram, that demonstrates the ways to load and render/parse the XAML UI:

 

XAML syntax terminologies

XAML uses some syntax terminologies to define an element in the UI and create the instance of it. Before you start working on it, you must understand the different terminologies that it offers. Let's have a look at a few of them.

 

Object element syntax

Each instance of a type is defined using proper XAML syntax to create an object element in the UI. Each of these object elements starts with a left angular bracket (<) and defines the name of the element. You can optionally prefix the namespace when it is defined outside the default scope. You can use a self-closing angular bracket (/>) or a right angular bracket (>) to close the object element definition. If the object element does not have any child elements, the self-closing angular bracket is used. For example, (<Button Content="Click Here" />) uses a self-closing angular bracket. If you write the same with a child element, it closes with an end tag (<Button>Click Here</Button>,) as shown.

When you define the object element in an XAML page, the instruction to create the instance of the element gets generated and it creates the instance by calling the constructor of the element when you load it in memory.

 

Property Attribute syntax

You can define one or more properties to an element. These are done by writing an attribute called Property Attribute syntax to the element. It starts with the name of the property and an assignment operator (=), followed by the value within quotes. The following example demonstrates how easy it is to define a button element to have a label as its content, and how to set its dimension in UI:

<Button Content="Click Here" /> 
<Button Content="Click Here" Width="120" Height="30" /> 
 

Property Element syntax

This is another type of XAML syntax that allows you to define the property as an element. This is often used when you cannot assign the value of the property within quotes. If we take the previous example, the text Click Here can be assigned to the button content easily. But, when you have another element or a composite property value, you cannot write those within the quotes. For this, XAML introduces Property Element syntax to help you to define the property value easily.

It starts with <element.PropertyName> and ends with </element.PropertyName>. The following example demonstrates how to assign a color to a button background with a SolidColorBrush object:

    <Button> 
      <Button.Background> 
         <SolidColorBrush Color="Red" /> 
      </Button.Background> 
    </Button> 
 

Content syntax

This is another type of XAML syntax that is used to set the content of a UI element. It can be set as the value of child elements. The following example demonstrates how to set the text content property of a Border control to hold a Button control as its child element:

    <Border> 
      <Border.Child> 
        <Button Content="Click Here" /> 
      </Border.Child> 
    </Border> 

While using Content syntax, you should remember the following points:

  • The value of a Content property must be contiguous
  • You cannot define an XAML Content property twice within a single instance

Thus, the following is invalid as it will throw XAML error:

    <Border> 
        <Border.Child> 
            <Button Content="Button One" /> 
        </Border.Child> 
        <Border.Child> 
            <Button Content="Button Two" /> 
        </Border.Child> 
    </Border> 
 

Collection syntax

When you need to define a collection of elements to the parent root, the Collection syntax is used to make it easy to read. For example, to add elements inside StackPanel, we use its Children property, as shown in the following code:

    <StackPanel>   
<StackPanel.Children> <Button Content="Button One" /> <Button Content="Button Two" /> </StackPanel.Children> </StackPanel>

This can be also written as follows, and the parser knows how to create and assign the elements to StackPanel:

    <StackPanel> 
      <Button Content="Button One" /> 
      <Button Content="Button Two" /> 
    </StackPanel> 
 

Event Attribute syntax

When you add a button, you need to associate an event listener to it, to perform some operation. The same is applicable for adding other controls and UI layouts. The XAML allows you to use the Event Attribute syntax to define events for a specific XAML object element.

The syntax looks like a property attribute, but it is used to associate the event listener to the element. The following example demonstrates how to assign the click event to a button control:

    <Button Content="Click Here" Click="OnButtonClicked" /> 

The associated event gets generated from the code behind the XAML page, where you can perform the real action. Here is the code snippet for the event implementation of the preceding button-click event:

    void OnButtonClicked (object sender, RoutedEventArgs e) 
    { 
        // event implementation 
    } 
 

Installing WPF Workload with Visual Studio 2017

As we have learned the basic concepts of WPF Architecture and XAML syntax, we can start to learn different recipes to build applications for Windows using the XAML tools for WPF. But, before that, let's install the required workload/components for Visual Studio 2017. If you are using prior versions of Visual Studio, this step will be different.

 

Getting ready

To install the required components for building WPF applications, run the Visual Studio 2017 installer. If you don't have the installer, you can go to https://www.visualstudio.com/downloads and download the correct edition. Let's download the Visual Studio Community 2017 edition as it is a fully featured IDE and available free for students, open source, and individual developers.

 

How to do it...

Once you have downloaded the Visual Studio 2017 installer, follow these steps to install the correct workload:

  1. Once you have run the installer, it will show you the following screen. Click on Continue:
  2. Wait for a few minutes to let the installer prepare itself for the installation process. A progress bar will show you the status of the current progress:
  3. Then the following screen will pop up, where it will ask you to select the workloads or components that you want to install:
  1. To build WPF applications targeting .NET Framework, select the .NET desktop development workload, as shown in the preceding screenshot.
  2. Click on the Install button to continue with the installation.
  3. The following screen will be displayed, showing the status of the installation. It will take some time, based on your internet bandwidth, as it's going to download the required components, based on your selection, from the Microsoft servers and install them one by one:
  1. Once the installation has completed, you may have to restart your system for the changes to take effect. In this case, a popup will appear on the screen, asking you to reboot your PC.

Once you have installed the .NET desktop development component and restarted your system, you are good to go with building your first WPF application.

 

Creating WPF applications

The WPF development platform supports a broad set of features that includes UI controls, layouts, resources, graphics, data binding, application model, and more. Before using each of those features, you need to create the WPF project using Visual Studio.

The goal of this recipe is to create a WPF project and learn the basic project structure and components. Let's start building our first WPF application using the XAML tools.

 

Getting ready

To get started with the WPF application development, you must have Visual Studio running on your system with the required components already installed on it.

 

How to do it...

Follow these steps to create your first WPF application:

  1. Inside your Visual Studio IDE, navigate to the File | New | Project... menu as shown in the following screenshot:
  2. This will open the New Project dialog on the screen. You can alternatively open it by pressing the keyboard shortcut Ctrl + Shift + N.
  3. In the New Project dialog, navigate to Installed | Templates | Visual C# | Windows Classic Desktop, as shown in the left-hand side of the following screenshot:
  1. In the right-hand side panel, first select the .NET Framework that you want your application to target. We have selected .NET Framework 4.7 here.
  2. Then select WPF App (.NET Framework), from the available list of templates.
  3. Give a name (in our case, it is CH01.HelloWPFDemo) to the project.
  4. Optionally, select the location of the project, where you want to create it.
  5. Optionally, you can also provide a different name for the Solution.
  6. When you are ready, click on the OK button to let Visual Studio create the project based on the template that you have selected.

Once the project has been created, Visual Studio will open the Solution Explorer, which lists the project with all the default files created on it. The project structure will look like the following screenshot:

 

There's more...

Each WPF application project created by Visual Studio using the default template consists of the following files:

  • App.config: This is the configuration file of your WPF application. By default, it contains the following lines that describe the supported runtime version for the application to run. This contains exactly the same runtime version that we selected during the project creation:
    <?xml version="1.0" encoding="utf-8" ?> 
      <configuration> 
        <startup>  
          <supportedRuntime            
version="v4.0"sku=".NETFramework,Version=v4.7" /> </startup> </configuration>

The config file can also contain application settings and other configuration settings that you want to use/refer in your application.

  • App.xaml: Visual Studio automatically creates the App.xaml file when you create a WPF project. It is the declarative starting point of your application. The root element of this file is the Application instance, which defines application specific properties and events:
    <Application x:Class="CH01.HelloWPFDemo.App" 
               
xmlns="http://schemas.microsoft.com/winfx
/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:CH01.HelloWPFDemo" StartupUri="MainWindow.xaml">
<Application.Resources> </Application.Resources> </Application>

The instance of the Application class defines the Window or a Page that's going to be the startup UI, and is registered with the StartupUri property. In the preceding code, (StartupUri="MainWindow.xaml") states that the MainWindow.xaml page will get loaded, once you run the application.

The application instance can also hold global/application-level resources (such as, Style, Template, and Converter) that can be used globally throughout the application.

  • App.xaml.cs: This is the code-behind class file of the App.xaml and extends the Application class of the framework to write application-specific code. You can use this file to subscribe to the events such as Startup, UnhandledException to perform common operations:
namespace CH01.HelloWPFDemo 
{ 
    /// <summary> 
    /// Interaction logic for App.xaml 
    /// </summary> 
    public partial class App : Application 
    { 
    } 
} 

This class is often used to manipulate command-line parameters and load different XAML pages based on that.

  • MainWindow.xaml: This is the default UI page that Visual Studio generates on creation of the WPF project. It is the page that gets registered as the StartupUri in App.xaml. The root element of this page is Window and it contains a Grid layout by default. Here is the default code snippet:
<Window x:Class="CH01.HelloWPFDemo.MainWindow" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> </Grid> </Window>

The x:Class attribute defines the associated partial class where the UI logic is being written. You can modify this XAML to provide a fresh look to your application start page. Various UI controls and layouts are going to be covered in the later chapters of this book.

  • MainWindow.xaml.cs: This is the code-behind class of MainWindow.xaml and contains the logic related to UI operations. In general, developers write implementations of various UI operations in this class.

Whenever you add any UI elements to an XAML page, the control gets registered internally in a partial class file that has .g.i.cs as the extension. For example, if you add a control in the MainWindow.xaml file, it gets registered in the MainWindow.g.i.cs residing in the obj folder. If you open the file, you can observe the entire loading process inside the InitializeComponent() method.

 

Creating and navigating from one window to another

In WPF standalone applications, a window is used to host the UI elements to enable users to interact with the UI and data. The base class Window provides all the APIs to create and interact with the Window UI.

In WPF applications, the generic window layout is divided into multiple parts. Here is a screenshot of a basic window, containing its various parts:

The various parts of the window are as mentioned here:

  • The outer part of the window is a Border, which you can utilize to enable the resizing option:
    • The outer border can contain a resizing grip, which enables you to resize the window diagonally
  • The window contains a Title bar at the top, which consists of the following parts:
    • An Icon to provide a unique brand to your application window
    • A Title, showing the identifiable name of the window
    • A small panel, containing Minimize, Maximise/Restore, and Close buttons
    • A System menu with menu items to allow users to perform Minimize, Maximize/ Restore, Move, Size, and Close operations on the window
  • A client area for the developers to add application/window specific layouts and controls
 

Getting ready

To get started with this recipe, open your Visual Studio instance and create a WPF project called CH01.WindowDemo based on the WPF App (.NET Framework) template. Once the project has been created, it will have files called MainWindow.xaml and MainWindow.xaml.cs, along with the other default files.

Let's get started with creating a new window in the same project and invoke a button to open the new window from the MainWindow.

 

How to do it...

To create a new window, follow these simple steps:

  1. Open the Solution Explorer and right-click on the project node.
  2. From the right-click context menu, navigate to Add | Window... as shown in the following screenshot:
  1. The following Add New Item dialog will appear on the screen:
  1. Make sure that the selected template is Window (WPF). Give it a name, SecondWindow.xaml, and click the Add button.
  2. This will create the SecondWindow.xaml file and its associated code-behind file SecondWindow.xaml.cs in the project directory.
  3. Open the XAML file (SecondWindow.xaml) and replace the entire contents with the following XAML code:
<Window x:Class="CH01.WindowDemo.SecondWindow" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Second Window" Height="200" Width="300"> <Grid> <TextBlock Text="Second Window Instance" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/> </Grid> </Window>
  1. Now open the MainWindow.xaml file to add a button into it. Replace the entire <Grid> </Grid> block, with the following XAML code:
<Grid> 
    <Button Content="Open Second Window" 
            Height="30" Width="150" 
            Click="OnSecondWindowButtonClicked"/> 
</Grid> 
  1. Now we need to add the implementation for the button-click event. Simply open the MainWindow.xaml.cs file and add the following lines of code inside the class definition:
private void OnSecondWindowButtonClicked(object sender,  
RoutedEventArgs e) 
{ 
    var window = new SecondWindow(); 
    window.Show(); 
} 
  1. Now, when you run the application, you will see that the MainWindow opens on the screen, containing a button labeled Open Second Window. Clicking on this button opens the second window on the screen that has text content of Second Window Instance. Here's the screenshot for your reference:
Please note that if you click the button again, it will create another instance of the second window because it's modeless.
 

How it works...

When you create the instance of the Window class, it will not become visible to the user. It only becomes visible when you call the Show() method, which returns the handle to the originated caller without waiting for the window to close.

When you call the Show() method, it basically creates a modeless window, and hence you can interact with other windows within the same application when the same is already open. The Window class also exposes a method called ShowDialog(), which creates a model window and prevent users from interacting with other windows of the application. We will discuss the more later in this chapter, in the Creating a dialog box section.

 

There's more...

The Window class provides you with a bunch of properties, methods, and events to customize the look of the window, and perform specific operations or to be notified of the current context. To ask the client area to support transparency, set the AllowsTransparency property of the window to true. This is often useful when you want to create a custom-shaped window or a skinned theme.

You can change the default icon of the window by setting the Icon property and enable/disable the window resizing by setting the ResizeMode property. You can also set the window title, startup location, window state, window style, and taskbar visibility by settings the Title, WindowStartupLocation, WindowState, WindowStyle, and ShowInTaskbar properties, respectively.

Not only these but you can bring the window to the foreground by calling its Activate() method and close the window by calling the Close() method available in the Window class. Sometimes, when you want to hide the window instead of quitting it completely, you can utilize the Hide() method to make the window hidden and bring it back again by calling the Show() method on the same instance.

The class also exposes some events to notify you of the current contextual information. You can use the Activated, Deactivated, Closing, Closed, and StateChanged, events in your code to get such notifications.

 

Creating and navigating from one page to another

The WPF application supports a browser style navigation mechanism, which can be used in both standalone applications as well as in XBAP applications. To implement it, WPF provides the Page class to encapsulate the Page content that can be navigated to and hosted by the browser, a NavigationWindow and/or a Frame.

 

Getting ready

To get started with this recipe to build an application that supports navigations mechanisms from one WPF page to another, open the Visual Studio IDE and create a project based on the WPF App (.NET Framework) template. Give it a name (in our case, it's CH01.PageDemo).

 

How to do it...

Once you have created your project based on the WPF App (.NET Framework) template, follow these steps to add pages to your project and integrate them with the NavigationService:

  1. Right-click on the project node where you want to create the pages.

  1. As shown in this screenshot, navigate to Add | Page... from the context menu:
  2. This will open the following Add New Item dialog window, where the item titled Page (WPF) is already selected. Give it a name, Page1.xaml and click Add. It will create the Page1.xaml and the associated code-behind file Page1.xaml.cs in your project:
  1. Now follow the same steps, 1 to 3, to create another page Page2.xaml, which will add both the XAML and associated C# code-behind file into the project.
  2. Open the Page1.xaml file and replace the Grid with the following XAML:
<Grid> 
    <TextBlock Text="This is Page 1" FontSize="20" 
               HorizontalAlignment="Center"       
               VerticalAlignment="Center"/> 
    <Button Content="Next" Height="30" Width="120"  
            Margin="20" 
            HorizontalAlignment="Right"  
            VerticalAlignment="Bottom" 
            Click="OnNextButtonClicked"/> 
</Grid>
  1. In the associated code-behind file (Page1.xaml.cs), add the following button-click event handler:
private void OnNextButtonClicked(object sender,
RoutedEventArgs e) { NavigationService.Navigate(new Uri("Page2.xaml",
UriKind.Relative)); }
  1. Similarly, add the following XAML into the Page2.xaml page, replacing the existing Grid:
<Grid> 
    <TextBlock Text="This is Page 2" FontSize="20" 
               HorizontalAlignment="Center"  
               VerticalAlignment="Center"/> 
    <Button Content="Previous" Height="30" Width="120"  
            Margin="20" 
            HorizontalAlignment="Right"  
            VerticalAlignment="Bottom" 
            Click="OnPreviousButtonClicked"/> 
</Grid> 
  1. Add the following button-click event handler into the Page2.xaml.cs file:
private void OnPreviousButtonClicked(object sender, RoutedEventArgs e) 
{ 
    if (NavigationService.CanGoBack) 
    { 
        NavigationService.GoBack(); 
    } 
} 
  1. Now open the MainWindow.xaml file and replace the XAML content with the following:
<NavigationWindow x:Class="CH01.PageDemo.MainWindow" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Source="Page1.xaml"> </NavigationWindow>
  1. Now open the MainWindow.xaml.cs file and change its base class to NavigationWindow, instead of Window.
  2. Run the application, which will open the following screen containing Page 1:
  1. Clicking on the Next button will navigate you to Page 2, as shown here, which contains the activated navigational button automatically provided by the WPF Framework:
  1. Now, if you click on the Previous button or the back button in the navigation panel, it will navigate you to Page 1.
 

How it works...

The NavigationWindow, which is defined in the MainWindow.xaml page, provides the basic mechanism to support the content navigation. The Source attribute (Source="Page1.xaml"), defined as URI, asks NavigationWindow to load the mentioned page (Page1.xaml) by default.

When you click on the Next button of Page1, the NavigationService.Navigate method executes, passing the URI of the page that you want to load next. The navigation buttons automatically activate based on the history of the navigation that you performed.

In Page2, when you click on the Previous button, it first checks whether the NavigationService has an immediate history item to navigate you to a previous page. If it finds a previous page, it then automatically navigates you to the desired page by calling the NavigationService.GoBack() method call. In this case, you don't have to pass the URI of the page.

 

There's more...

NavigationService offers a variety of properties, methods, and events to perform navigation mechanisms on your page content. CanGoBack() and CanGoForward() return a Boolean value indicating whether there is at least one entry in the back and forward navigation history, respectively. The method GoBack() navigates you to the most recent entry from back navigation history, whereas the GoForward() method navigates you to the forward navigation history, if there's one available.

To refresh the current content, you can call the Refresh() method. The StopLoading() method stops the current execution from downloading/loading the content part of the current navigation context. You can also programmatically add or remove an entry from the navigation history. The AddBackEntry method takes a parameter for the CustomContentState object to add the entry into the back-navigation history. The RemoveBackEntry() method removes the most recent entry from the back-navigation history.

Events such as Navigating, Navigated, NavigationFailed, NavigationStopped, NavigationProgress, and LoadCompleted are there to notify you of the various statuses of the current navigation process. Use them wisely, based on your requirements.

 

Creating a dialog box

A dialog box is also a kind of window, and is generally used to get some inputs from the user or to show a message to the user. It uses a model window to prevent users from interacting with other windows of the same application when it is already open. In this recipe, we will learn how to create a model dialog and use the common dialog boxes that the framework provides.

 

Getting ready

To get started with building and using dialog boxes in a WPF application, open your Visual Studio IDE and create a new WPF project, calling it CH01.DialogBoxDemo.

 

How to do it...

Follow these steps to create the dialog window and invoke it from the MainWindow to show a message to the user:

  1. Open the Solution Explorer and right-click on the project node.
  2. From the context menu, select Add | Window... to open the Add New Item dialog.
  3. Making sure that the Window (WPF) template is selected, give it the name MessageDialog, and click Add to continue. This will create MessageDialog.xaml and MessageDialog.xaml.cs files in the project.
  4. Open the MessageDialog.xaml file and replace the entire XAML content with the following:
<Window x:Class="CH01.DialogBoxDemo.MessageDialog" 
 xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ShowInTaskbar="False" WindowStyle="SingleBorderWindow" Title="Message" Height="150" Width="400" FontSize="14" Topmost="True" ResizeMode="NoResize">
<Grid> <TextBlock TextWrapping="Wrap" Margin="8" Text="Thank you for reading 'Windows Presentation
Foundation Cookbook'. Click 'OK' to continue next."/> <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="4"> <Button Content="OK" Width="60" Height="30" Margin="4" IsDefault="True" Click="OnOKClicked"/> <Button Content="Cancel" Width="60" Height="30" Margin="4" IsCancel="True" Click="OnCancelClicked"/> </StackPanel> </Grid> </Window>
  1. Open the MessageDialog.xaml.cs file, and add the following event implementations for the OK button and Cancel button:
private void OnOKClicked(object sender, RoutedEventArgs e) 
{ 
    DialogResult = true; 
} 
 
private void OnCancelClicked(object sender, RoutedEventArgs e) 
{ 
    DialogResult = false; 
} 
  1. Now open the MainWindow.xaml page and replace the Grid with the following XAML content:
<Grid> 
    <ListBox x:Name="result" Height="100" Margin="8" 
             HorizontalAlignment="Stretch"  
             VerticalAlignment="Top" /> 
    <Button Content="Show Message" Width="150" Height="30"  
            VerticalAlignment="Bottom" Margin="8" 
            Click="OnShowMessageButtonClicked"/> 
</Grid> 
  1. Go to the code-behind file, MainWindow.xaml.cs, and add the button event implementation as shared in the following code section:
private void OnShowMessageButtonClicked(object sender, RoutedEventArgs e) 
{ 
    var messageDialog = new MessageDialog(); 
    var dialogResult = messageDialog.ShowDialog(); 
 
    if (dialogResult == true) 
    { 
        result.Items.Add("You clicked 'OK' button."); 
    } 
    else if (dialogResult == false) 
    { 
        result.Items.Add("You clicked 'Cancel' button."); 
    } 
}
  1. Now run the application. The visible window will have a button labeled Show Message. Click on it to invoke the message dialog window that we have created:
  1. Click on the Cancel button, which will add You clicked 'Cancel' button text into the list present in the MainWindow.
  2. Launch the message window again and click on the OK button. This will add You clicked 'OK' button in the list.
 

How it works...

When you call the ShowDialog() method of the Window instance, it opens it as a model dialog and waits until the user provides an input to it. In this case, the user input is the interaction with the OK and Cancel button. When you click the OK button, the associated event handler assigns true to the DialogResult property and returns to the caller. Similarly, the Cancel button event handler, assigns false to the DialogResult property and returns.

Based on the return value of the ShowDialog() method, which actually returns the value of DialogResult, you can decide whether the user clicked the OK or Cancel button.

The dialog window has been customized by setting the following properties to the Window instance:

  • The ShowInTaskbar property has been set to False to prevent the window from being visible in the Taskbar.
  • The WindowStyle property has been set to SingleBorderWindow to add a thin border to the window, removing the minimize and maximize buttons from the title bar.
  • The Topmost property has been set to True to keep it always visible on top of other windows. This is optional, but good to have.
  • The ResizeMode property has been set to NoResize to prevent the user from resizing the dialog window.
 

There's more...

The operating system provides some reusable dialog boxes, which provide a user experience consistent with the version of the operating system in which the application is running. The experience also stays consistent across all applications to provide a unique interface for performing common operations such as opening files, saving files, printing files, color selection, and more.

WPF provides these reusable, common dialog boxes as managed wrapper classes, encapsulating the core implementation. This reduces the extra effort creating and managing the common operations.

 

Using the open file dialog

To open files in your WPF application, you can use the managed wrapper class OpenFileDialog, which is present under the Microsoft.Win32 namespace. You just have to create the instance and call the ShowDialog() method by optionally setting a few properties for UI customization.

A basic open file dialog looks like the following screenshot, providing you with an option to select one or more files to open:

The following code snippet demonstrates how to initiate the open file dialog by optionally filling the file-extension filter:

private void OnOpenButtonClicked(object sender, RoutedEventArgs e) 
{ 
    var openfileDialog = new OpenFileDialog 
    { 
        Filter = "Text documents (.txt) | *.txt | Log files (.log) | 
*.log" }; var dialogResult = openfileDialog.ShowDialog(); if (dialogResult == true) { var fileName = openfileDialog.FileName; } }

The dialogResult returned by the ShowDialog() method tells us whether the operation was performed successfully. Based on that, you can call the instance of the file dialog to get more details about the selected file.

 

Using the save file dialog

Along with the OpenFileDialog interface, the Microsoft.Win32 namespace also provides the SaveFileDialog managed wrapper to perform file saving operations from your WPF application. Similar to the open file dialog, you need to create the instance of it by optionally filling its various properties to finally call the ShowDialog() method.

The save file dialog looks like the following screenshot, where you can provide a name to save as a file:

Optionally, you can set the extension filter, default file name, and other properties before launching the dialog window, as shown in the following code snippet:

private void OnSaveButtonClicked(object sender, RoutedEventArgs e) 
{ 
    var saveFileDialog = new SaveFileDialog 
    { 
        Filter = "Text documents (.txt) | *.txt | Log files (.log) |
*.log" }; var dialogResult = saveFileDialog.ShowDialog(); if (dialogResult == true) { var fileName = saveFileDialog.FileName; } }

Based on the dialogResult returned by the ShowDialog() call you can decide whether the save was successful and retrieve more information about the saved file from the file dialog instance.

 

Using the print dialog

The managed wrapper PrintDialog is also present in the Microsoft.Win32 namespace, and provides you with the interface to call the operating system's printer properties and perform the print operation. The dialog gives you the option to Select Printer, configure the printing preferences, and select the page range and other parameters, as shown in the following screenshot:

To invoke the same, just create the instance of the PrintDialog and call its ShowDialog() method. You can optionally set page range, printable area, and other properties. If the dialogResult returned by the ShowDialog() method is set to true, it confirms that the printing job has been queued up successfully, and based on that you can perform the next set of actions.

Here's the code snippet for your reference:

private void OnPrintButtonClicked(object sender, RoutedEventArgs e) 
{ 
    var printDialog = new PrintDialog(); 
    var dialogResult = printDialog.ShowDialog(); 
 
    if (dialogResult == true) 
    { 
        // perform the print operation 
    } 
} 
 

Other common dialogs

WPF also provides some other common dialog boxes to perform the selection of various formatting options, such as font, font style, font size, text effects, and color. You can use the FontDialog and ColorDialog, present under the System.Windows.Forms namespace, to add support for the font and color selections, respectively.

Here's the screenshot presenting the font selector and color selector dialogs:

 

Creating ownership between windows

In the WPF application, the window objects that you create are independent of each other by default. But, sometimes, you may want to create an owner-owned relationship between them. For example, the toolbox window that you generally see in your Visual Studio IDE and/or in a Photoshop application.

When you set an owner of a window, it acts according to the owner instance. For example, if you minimize or close the owner window, the other window under the owner-owned relationship automatically minimizes or closes according to its owner.

Let's begin creating this recipe to have an owner-owned relationship between two windows.

 

Getting ready

To get started with this recipe, open your Visual Studio IDE and create a new WPF project called CH01.OwnershipDemo.

 

How to do it...

Perform the following steps to create a ToolBox window and assign its ownership to the MainWindow, so that it can act according to its owner:

  1. Right-click on the project node and select Add | Window... from the context menu. The Add New Item dialog will be shown on the screen.
  2. Select Window (WPF) from the available list, give it the name ToolBox, and click Add to continue. This will add ToolBox.xaml and ToolBox.xaml.cs into your project.
  3. Open the ToolBox.xaml file and replace its content with the following XAML code:
<Window x:Class="CH01.OwnershipDemo.ToolBox" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" SizeToContent="WidthAndHeight" ResizeMode="NoResize" Title="ToolBox"> <StackPanel Margin="10"> <Button Content="Bold" Width="70" Margin="4"/> <Button Content="Italics" Width="70" Margin="4"/> <Button Content="Underlined" Width="70" Margin="4"/> </StackPanel> </Window>
  1. Now open the App.xaml page and remove the property attribute StartupUri, defined as (StartupUri="MainWindow.xaml") from it.
  2. Go to its code-behind file App.xaml.cs and override the OnStartup event. We need to modify the implementation according to our needs. Replace the entire OnStartup event handler with the following code block:
protected override void OnStartup(StartupEventArgs e) 
{ 
    base.OnStartup(e); 
 
    var mainWindow = new MainWindow(); 
    mainWindow.Show(); // must show before setting it
as owner of some other window var toolBox = new ToolBox { Owner = mainWindow }; toolBox.Show(); }
  1. Run the application to see the relationship between the two windows. The windows will look like the following screenshot:
  2. Drag the ToolBox window and you can see that you are able to move it outside the MainWindow. Now perform some operations, such as minimizing and closing, on the MainWindow, and you will see that the ToolBox window also acts according to its owner.
 

How it works...

By default, the owner of every Window object is set to null, and thus each window is independent of the other. But, when you set its owner, it follows the owner-owned relationship and acts with the owner window.

Window ownership is not a feature of WPF, but a capability of the Win32 user API and, accessible from a WPF application.

 

There's more...

Make sure you display the owner window first, before setting it as the owner of some other window, otherwise the system will throw an InvalidOperationException:

Some points to note about window ownership:

  • The window that has an ownership relationship with another window always appears on top of that owner
  • You can drag the window outside the owner window
  • When you minimize or close the owner, the other window, which is related to it, will follow the owner and minimize or close respectively
  • By default, the window in a relationship gets displayed in the taskbar, but when you minimize the owner, it gets removed from the taskbar
  • When you want to break the relationship, just set the Owner property to null
 

Creating a single instance application

When you build applications for Windows, there are many reasons why you would want to restrict users from launching multiple instances of your application. Some common examples are installers, uninstallers, update utilities, media applications, utility tools, and so on.

In a normal application, when you launch the app, it creates a Windows process, and allocates its own memory space and resources. But, when you don't want to create multiple instances of the process for a single application that is already running, you want to silently quit the new instance and bring the running process into the foreground.

In this recipe, we will learn how to achieve this using Mutex (Mutual Exclusion) and unmanaged code.

 

Getting ready

To get started with this, open your Visual Studio instance and create a new project based on the WPF application template. During the project creation, give it the name CH01.SingleInstanceDemo.

 

How to do it...

Once the WPF project has been created, follow these steps to create a single instance of the WPF application:

  1. Run the application by pressing the CTRL + F5 key combination. This will launch one instance of the application.

  1. Press CTRL + F5 multiple times to launch multiple instances of the application. Now it's time to make the application a single instance application:
  2. Close all the running processes and then follow the next steps to implement the single instance behavior.
  3. Open the MainWindow.xaml and add the window title to Single Instance Demo. Here you can find the entire XAML code:
<Window x:Class="CH01.SingleInstanceDemo.MainWindow" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Single Instance Demo" Height="250" Width="400"> <Grid> </Grid> </Window>
  1. Open the App.xaml.cs file and override the base implementation of the OnStartup method.
  2. Change the code of the OnStartup method so that it looks like the following code:
protected override void OnStartup(StartupEventArgs e) 
{ 
  base.OnStartup(e); 
 
  var mutex = new Mutex(true, "SingleInstanceDemo",  
  out bool isNewInstance); 
  if (!isNewInstance) 
  { 
    MessageBox.Show("Application instance is  
     already running!"); 
    Shutdown(); 
  } 
} 
  1. Add the System.Threading namespace declaration, so that the Mutex can be discoverable. The Mutex resides in the aforesaid namespace.
  2. Now compile the project to make sure that there are no compiler errors.
  3. Press CTRL + F5, which will run the first instance of the application.
  4. Now return to the Visual Studio, without closing the application, and then hit CTRL + F5. This time, instead of launching the application UI, an Application instance is already running! message will pop up on the screen. Clicking OK will close the message.
  5. Press CTRL + F5 again. Observe that no second instance of the UI is visible on the screen.
 

How it works...

It's a trick to handle the application to have only a single instance. The Mutex (Mutual Exclusion) object is used to define the instance with a unique name. Here we called it SingleInstanceDemo. The Boolean out parameter returns whether the current calling thread has been granted the initial ownership of the mutex object.

A Mutex object is a synchronization object, which is generally used to synchronize access to a shared resource, so that only one thread can access that resource at a single point in time.

For the first instance of the application, it will be granted as the initial ownership. When the second instance runs, the calling thread will not get the initial ownership because the mutex object with the same name, SingleInstanceDemo, already exists and is running.

So, the Boolean value of isNewInstance will be false and the message box will get displayed on the screen. The second instance of the application is still running at that moment and calls the Shutdown() method when you click on the OK button to close the message box.

Thus, the second instance will be removed from the process list. The first instance will continue running on the system.

 

There's more...

There could be a scenario where the application is running in a background process and the user tries to relaunch the application. In such a scenario, instead of showing a message to the user, you may want to activate the already running application and show its UI.

You can do this by changing a bit of the existing code and integrating an unmanaged code call. To do so, open the App.xaml.cs file once again and follow these steps:

  1. Add the following using namespace into the file: System.Runtime.InteropServices.
  2. Then, you need to add the following unmanaged code declaration from the user32.dll to the App.xaml.cs file:
[DllImport("user32", CharSet = CharSet.Unicode)] 
static extern IntPtr FindWindow(string cls, string win); 
 
[DllImport("user32")] 
static extern IntPtr SetForegroundWindow(IntPtr hWnd);
  1. Add the following method to activate the already running window, provided that the title of the window is static. In our case, it is Single Instance Demo, modified in the MainWindow.xaml page:
private static void ActivateWindow() 
{ 
    var otherWindow = FindWindow(null, "Single Instance Demo"); 
    if (otherWindow != IntPtr.Zero) 
    { 
        SetForegroundWindow(otherWindow); 
    } 
} 
  1. Now, instead of calling the MessageBox, call the ActivateWindow() method in the OnStartup. Here, you can find this new code:
protected override void OnStartup(StartupEventArgs e) 
{ 
    base.OnStartup(e); 
 
    var mutex = new Mutex(true,  
     "SingleInstanceDemo",  
     out bool isNewInstance); 
    if (!isNewInstance) 
    { 
        // MessageBox.Show("Application instance is  
           already running!"); 
        ActivateWindow(); 
        Shutdown(); 
    } 
} 
  1. Now run the application. It will launch the MainWindow titled Single Instance Demo on the screen.
  2. Return to Visual Studio. This will put the application window in the background. Now run the application once again by pressing the keyboard shortcut CTRL + F5. This time, instead of running a different instance to show the UI, it will activate the existing window and push the running application to foreground.

It's not mandatory that the application window must always have a static title. In such cases, it will become more complex to handle said scenario.

 

Passing arguments to WPF applications

The command-line arguments are used to take optional parameters or values from the user, while launching the application. These are generally used to perform specific commands on the application from the outside.

In this recipe, we will learn how to pass command-line arguments to a WPF application.

 

Getting ready

To get started, open the Visual Studio IDE and create a WPF application project called CH01.CommandLineArgumentDemo.

 

How to do it...

Now follow these steps to let the application support command line arguments and perform actions based on those:

  1. Open the MainWindow.xaml to add a TextBlock into the Grid panel. Replace the entire XAML content with the following lines:
<Window x:Class="CH01.CommandLineArgumentDemo.MainWindow" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Main Window" Height="200" Width="400"> <Grid> <TextBlock Text="This is 'Main Window'
of the application." HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" /> </Grid> </Window>
  1. Create a new window in the project by right-clicking on the project node and then following the context menu path Add | Window... to open the Add New Item dialog window. Give it the name OtherWindow and click the Add button. This will add OtherWindow.xaml and OtherWindow.xaml.cs into the project.

  1. Now open the OtherWindow.xaml and change its UI to have different text. Let's replace the entire XAML code with the following lines:
<Window x:Class="CH01.CommandLineArgumentDemo.OtherWindow" 
xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Other Window" Height="200" Width="400"> <Grid> <TextBlock Text="This is 'Other Window' of the
application." HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" /> </Grid> </Window>
  1. Now open the App.xaml and remove the StartupUri="MainWindow.xaml". This has been done to control the launch of the proper window, based on the argument passed to the application.
  2. Open the App.xaml.cs and override its OnStartup method to retrieve the arguments passed to it and open the desired window based on that. Let's add the following code implementation for the OnStartup method:
protected override void OnStartup(StartupEventArgs e) 
{ 
    base.OnStartup(e); 
 
    var args = e.Args; 
    if (args.Contains("/other"))  
    {  
        new OtherWindow().Show();  
    } 
    else  
    {  
        new MainWindow().Show();  
    } 
} 
  1. Now build the project. Navigate to the bin\Debug folder and launch a Command Window in that location. Alternatively, you can launch a Command Window (cmd.exe) and navigate to the bin\Debug path, where your application is available.

  1. In the console window, enter the name of the application without passing any arguments to it, as shown in the following command:
      CH01.CommandLineArgumentDemo.exe
  1. This will launch the MainWindow of our application, with this screen:
  2. Close the application window and, from the console window, enter the application name by specifying the /other argument to it, as shown in the following command:
      CH01.CommandLineArgumentDemo.exe /other
  1. This will launch the OtherWindow of the application, instead of the MainWindow:
 

How it works...

The OnStartup(StartupEventArgs e) method signature contains StartupEventArgs as a method parameter. It contains a property, Args, that returns a string array of the command line arguments that were passed to the application. If no command line arguments were passed, the string array will have zero items in it.

Now, by checking the condition, we launch the desired window that we want to show to the user. You can also take arguments such that the application launches in normal mode, maximized mode, or minimized. You can also use it to open the application as hidden, in some specific cases.

 

There's more...

As we have seen how to launch the WPF application from the command line by passing the arguments, let's learn how to do this from Visual Studio itself to launch it in debug mode.

To pass a command line argument to your WPF application from Visual Studio in debug mode, right-click on the project node and click Properties from the context menu entry. This will open the project properties. Now navigate to the Debug tab. Please refer to the following screenshot:

Under Start options, enter /other as the command line arguments. Now run the application in debug mode by pressing F5. You will see that the OtherWindow opens on the screen. To launch the MainWindow, just remove the /other argument from the project properties mentioned earlier and run the application again. This time you will see that the MainWindow opens instead of the OtherWindow.

 

Handling unhandled exceptions

Exception handling is a vital part of software development. When an exception occurs at runtime, due to any error in the code, we handle those with a try {} catch {} block. The try {} block contains the code where the exception occurred; the catch {} block knows how to handle that, based on the type of the exception. After the exception has been handled, the normal execution of the program continues without affecting the application.

Though, in most of the cases we handle, there could be cases that may go unnoticed and come into the picture at runtime. Such an unhandled exception crashes the application. In this recipe, we will learn how to catch the unhandled exceptions in the WPF application and close the application properly.

 

Getting ready

To get started, open the Visual Studio IDE. Now create a new project, based on the WPF Application template, and call it CH01.UnhandledExceptionDemo.

 

How to do it...

Let's start the demonstration by following these steps:

  1. Open the MainWindow.xaml page, and add two radio buttons and one button on it. The first radio button will cause an exception handled in a try {} catch {} block, whereas the second radio button will throw an exception that will go unhandled. Add the following code into your MainWindow.xaml:
<Window x:Class="CH01.UnhandledExceptionDemo.MainWindow" 
  xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="UnhandledException Demo" Height="120" Width="400"> <Grid Margin="10"> <StackPanel Orientation="Vertical"> <RadioButton x:Name="radioOne" GroupName="type" Content="Handle in Try/Catch Block" IsChecked="True" Margin="4"/> <RadioButton x:Name="radioTwo" GroupName="type" Content="Handle in Unhandled Block" IsChecked="False" Margin="4"/> </StackPanel> <Button Content="Throw Exception" Width="120" Height="30" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10" Click="OnThrowExceptionClicked"/> </Grid> </Window>
  1. Open the MainWindow.xaml.cs file to add the button-click event handler. Add the following code block inside the class:
private void OnThrowExceptionClicked(object sender, RoutedEventArgs e) 
{ 
    if (radioOne.IsChecked == true) 
    { 
        try { throw new Exception("Demo Exception"); } 
        catch (Exception ex) 
        { 
            MessageBox.Show("'" + ex.Message +  
                  "' handled in Try/Catch block"); 
        } 
    } 
    else 
    { 
        throw new Exception("Demo Exception"); 
    } 
} 
  1. Go to the App.xaml.cs file and override the OnStartup method to have the application level DispatcherUnhandledException event registered as shown in the following code:
protected override void OnStartup(StartupEventArgs e) 
{ 
    base.OnStartup(e); 
 
    DispatcherUnhandledException += OnUnhandledException; 
}
  1. Add the DispatcherUnhandledException event handler into the App.xaml.cs and handle the exception as shown in the following code, but with an empty code block:
private void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) 
{ 
 
} 
  1. Let's build and run the application. You will see the following UI on the screen:
  2. It will have two radio selectors and one button in the application window. When the first radio button is checked and you click on the Throw Exception button, it will generate an exception in a try {} block, which will then immediately be handled by the associated catch {} block without crashing the application. The following message box will be shown on the UI:
  1. For the second radio button, when checked, if you click on the Throw Exception button, the exception will go unhandled and will be caught in the App.xaml.cs file, under the OnUnhandledException event, and the application will crash:
  1. Open the App.xaml.cs once again and modify the OnUnhandledException event implementation, as follows, to handle the thrown exception:
private void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) 
{ 
    e.Handled = true; 
} 
  1. Now run the application once again, check the second radio button and click on the button. You will notice that the application will not crash this time.
  2. Click the Throw Exception button multiple times. The application will continue as-is, without causing any crash of the UI.
 

How it works...

When you handle this kind of uncaught/unhandled exception by specifying e.Handled = true, your application will not crash and will continue running. The best part of catching an unhandled exception is logging the unknown/unhandled errors, so that you can investigate the root cause behind these exceptions and fix them in future builds.

When there's a critical error, you can restart the application programmatically from this block.

 

There's more...

You can also use the AppDomain.CurrentDomain.UnhandledException event handler to catch any unhandled exceptions, but you won't be able to handle it in a way to continue running the application. When used, you can log the error and terminate/restart the application.

Unhandled exceptions handled in the DispatcherUnhandledException event, by specifying e.Handled = true will not route to the AppDomain.CurrentDomain.UnhandledException.
Latest Reviews (4 reviews total)
Goed goed goed goed goed g
Je n'ai pas réussi à m'inscrire sur votre site et à recevoir la possibilité de télécharger mon EBook. Je n'ai jamais reçu l'email de confirmation d'inscription.
Excellent book, very completed
Windows Presentation Foundation Development Cookbook
Unlock this book and the full library FREE for 7 days
Start now