Permalink
Fetching contributors…
Cannot retrieve contributors at this time
168 lines (110 sloc) 16 KB
title ms.date dev_langs helpviewer_keywords ms.assetid
Building a WPF Application (WPF)
03/30/2017
csharp
vb
WPF application [WPF], building
a58696fd-bdad-4b55-9759-136dfdf8b91c

Building a WPF Application (WPF)

Windows Presentation Foundation (WPF) applications can be built as [!INCLUDEdnprdnshort] executables (.exe), libraries (.dll), or a combination of both types of assemblies. This topic introduces how to build [!INCLUDETLA2#tla_wpf] applications and describes the key steps in the build process.

Building a WPF Application

A WPF application can be compiled in the following ways:

WPF Build Pipeline

When a [!INCLUDETLA2#tla_wpf] project is built, the combination of language-specific and [!INCLUDETLA2#tla_wpf]-specific targets are invoked. The process of executing these targets is called the build pipeline, and the key steps are illustrated by the following figure.

WPF build process

Pre-Build Initializations

Before building, [!INCLUDETLA2#tla_msbuild] determines the location of important tools and libraries, including the following:

  • The .NET Framework.

  • The [!INCLUDETLA2#tla_wcsdk] directories.

  • The location of [!INCLUDETLA2#tla_wpf] reference assemblies.

  • The property for the assembly search paths.

The first location where [!INCLUDETLA2#tla_msbuild] searches for assemblies is the reference assembly directory (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\). During this step, the build process also initializes the various properties and item groups and performs any required cleanup work.

Resolving References

The build process locates and binds the assemblies required to build the application project. This logic is contained in the ResolveAssemblyReference task. All assemblies declared as Reference in the project file are provided to the task along with information on the search paths and metadata on assemblies already installed on the system. The task looks up assemblies and uses the installed assembly's metadata to filter out those core [!INCLUDETLA2#tla_wpf] assemblies that need not show up in the output manifests. This is done to avoid redundant information in the ClickOnce manifests. For example, since PresentationFramework.dll can be considered representative of an application built on and for the [!INCLUDETLA2#tla_wpf] and moreover since all [!INCLUDETLA2#tla_wpf] assemblies exist at the same location on every machine that has the .NET Framework installed, there is no need to include all information on all .NET Framework reference assemblies in the manifests.

Markup Compilation—Pass 1

In this step, [!INCLUDETLA2#tla_xaml] files are parsed and compiled so that the runtime does not spend time parsing [!INCLUDETLA2#tla_xml] and validating property values. The compiled [!INCLUDETLA2#tla_xaml] file is pre-tokenized so that, at run time, loading it should be much faster than loading a [!INCLUDETLA2#tla_xaml] file.

During this step, the following activities take place for every [!INCLUDETLA2#tla_xaml] file that is a Page build item:

  1. The [!INCLUDETLA2#tla_xaml] file is parsed by the markup compiler.

  2. A compiled representation is created for that [!INCLUDETLA2#tla_xaml] and copied to the obj\Release folder.

  3. A CodeDOM representation of a new partial class is created and copied to the obj\Release folder.

In addition, a language-specific code file is generated for every [!INCLUDETLA2#tla_xaml] file. For example, for a Page1.xaml page in a Visual Basic project, a Page1.g.vb is generated; for a Page1.xaml page in a C# project, a Page1.g.cs is generated. The ".g" in the file name indicates the file is generated code that has a partial class declaration for the top-level element of the markup file (such as Page or Window). The class is declared with the partial modifier in C# (Extends in Visual Basic) to indicate there is another declaration for the class elsewhere, usually in the code-behind file Page1.xaml.cs.

The partial class extends from the appropriate base class (such as xref:System.Windows.Controls.Page for a page) and implements the xref:System.Windows.Markup.IComponentConnector?displayProperty=nameWithType interface. The xref:System.Windows.Markup.IComponentConnector interface has methods to initialize a component and connect names and events on elements in its content. Consequently, the generated code file has a method implementation like the following:

public void InitializeComponent() {  
    if (_contentLoaded) {  
        return;  
    }  
    _contentLoaded = true;  
    System.Uri resourceLocater =   
        new System.Uri(  
            "window1.xaml",   
            System.UriKind.RelativeOrAbsolute);  
    System.Windows.Application.LoadComponent(this, resourceLocater);  
}  
Public Sub InitializeComponent() _  
  
    If _contentLoaded Then  
        Return  
    End If  
  
    _contentLoaded = True  
    Dim resourceLocater As System.Uri = _  
        New System.Uri("mainwindow.xaml", System.UriKind.Relative)  
  
    System.Windows.Application.LoadComponent(Me, resourceLocater)  
  
End Sub  

By default, markup compilation runs in the same xref:System.AppDomain as the [!INCLUDETLA2#tla_msbuild] engine. This provides significant performance gains. This behavior can be toggled with the AlwaysCompileMarkupFilesInSeparateDomain property. This has the advantage of unloading all reference assemblies by unloading the separate xref:System.AppDomain.

Markup Compilation—Pass 2

Not all [!INCLUDETLA2#tla_xaml] pages are compiled at during pass 1 of markup compilation. [!INCLUDETLA2#tla_xaml] files that have locally defined type references (references to types defined in code elsewhere in the same project) are exempt from compilation at this time. This is because those locally defined types exist only in source and have not yet been compiled. In order to determine this, the parser uses heuristics that involve looking for items such as x:Name in the markup file. When such an instance is found, that markup file’s compilation is postponed until the code files have been compiled, after which, the second markup compilation pass processes these files.

File Classification

The build process puts output files into different resource groups based on which application assembly they will be placed in. In a typical nonlocalized application, all data files marked as Resource are placed in the main assembly (executable or library). When UICulture is set in the project, all compiled [!INCLUDETLA2#tla_xaml] files and those resources specifically marked as language-specific are placed in the satellite resource assembly. Furthermore, all language-neutral resources are placed in the main assembly. In this step of the build process, that determination is made.

The ApplicationDefinition, Page, and Resource build actions in the project file can be augmented with the Localizable metadata (acceptable values are true and false), which dictates whether the file is language-specific or language-neutral.

Core Compilation

The core compile step involves compilation of code files. This is orchestrated by logic in the language-specific targets files Microsoft.CSharp.targets and Microsoft.VisualBasic.targets. If heuristics have determined that a single pass of the markup compiler is sufficient, then the main assembly is generated. However, if one or more [!INCLUDETLA2#tla_xaml] files in the project have references to locally defined types, then a temporary .dll file is generated so the final application assemblies may be created after the second pass of markup compilation is complete.

Manifest Generation

At the end of the build process, after all the application assemblies and content files are ready, the [!INCLUDETLA2#tla_clickonce] manifests for the application are generated.

The deployment manifest file describes the deployment model: the current version, update behavior, and publisher identity along with digital signature. This manifest is intended to be authored by administrators who handle deployment. The file extension is .xbap (for [!INCLUDETLA#tla_xbap#plural]) and .application for installed applications. The former is dictated by the HostInBrowser project property and as a result the manifest identifies the application as browser-hosted.

The application manifest (an .exe.manifest file) describes the application assemblies and dependent libraries and lists permissions required by the application. This file is intended to be authored by the application developer. In order to launch a [!INCLUDETLA2#tla_clickonce] application, a user opens the application's deployment manifest file.

These manifest files are always created for [!INCLUDETLA2#tla_xbap#plural]. For installed applications, they are not created unless the GenerateManifests property is specified in the project file with value true.

[!INCLUDETLA2#tla_xbap#plural] get two additional permissions over and above those permissions assigned to typical Internet zone applications: xref:System.Security.Permissions.WebBrowserPermission and xref:System.Security.Permissions.MediaPermission. The [!INCLUDETLA2#tla_wpf] build system declares those permissions in the application manifest.

Incremental Build Support

The [!INCLUDETLA2#tla_wpf] build system provides support for incremental builds. It is fairly intelligent about detecting changes made to markup or code, and it compiles only those artifacts affected by the change. The incremental build mechanism uses the following files:

  • An $(AssemblyName)_MarkupCompiler.Cache file to maintain current compiler state.

  • An $(AssemblyName)_MarkupCompiler.lref file to cache the [!INCLUDETLA2#tla_xaml] files with references to locally defined types.

The following is a set of rules governing incremental build:

  • The file is the smallest unit at which the build system detects change. So, for a code file, the build system cannot tell if a type was changed or if code was added. The same holds for project files.

  • The incremental build mechanism must be cognizant that a [!INCLUDETLA2#tla_xaml] page either defines a class or uses other classes.

  • If Reference entries change, then recompile all pages.

  • If a code file changes, recompile all pages with locally defined type references.

  • If a [!INCLUDETLA2#tla_xaml] file changes:

    • If [!INCLUDETLA2#tla_xaml] is declared as Page in the project: if the [!INCLUDETLA2#tla_xaml] does not have locally defined type references, recompile that [!INCLUDETLA2#tla_xaml] plus all [!INCLUDETLA2#tla_xaml] pages with local references; if the [!INCLUDETLA2#tla_xaml] has local references, recompile all [!INCLUDETLA2#tla_xaml] pages with local references.

    • If [!INCLUDETLA2#tla_xaml] is declared as ApplicationDefinition in the project: recompile all [!INCLUDETLA2#tla_xaml] pages (reason: each [!INCLUDETLA2#tla_xaml] has reference to an xref:System.Windows.Application type that may have changed).

  • If the project file declares a code file as application definition instead of a [!INCLUDETLA2#tla_xaml] file:

    • Check if the ApplicationClassName value in the project file has changed (is there a new application type?). If so, recompile the entire application.

    • Otherwise, recompile all [!INCLUDETLA2#tla_xaml] pages with local references.

  • If a project file changes: apply all preceding rules and see what needs to be recompiled. Changes to the following properties trigger a complete recompile: AssemblyName, IntermediateOutputPath, RootNamespace, and HostInBrowser.

The following recompile scenarios are possible:

  • The entire application is recompiled.

  • Only those [!INCLUDETLA2#tla_xaml] files that have locally defined type references are recompiled.

  • Nothing is recompiled (if nothing in the project has changed).

See Also

Deploying a WPF Application
WPF MSBuild Reference
Pack URIs in WPF
WPF Application Resource, Content, and Data Files