Dotnet Desktop WPF App Development
Dotnet Desktop WPF App Development
Application Development
Article • 05/07/2025
XAML browser applications (XBAPs) (applications composed of navigation pages that are
built as executable assemblies and hosted by Web browsers such as Microsoft Internet
Explorer or Mozilla Firefox).
7 Note
Using WPF types in a Windows service is strongly discouraged. If you attempt to use these
features in a Windows service, they may not work as expected.
To build this set of applications, WPF implements a host of services. This topic provides an
overview of these services and where to find more information.
Application Management
Executable WPF applications commonly require a core set of functionality that includes the
following:
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions
of Firefox. These older browsers are usually unsupported on Windows 10 and
Windows 11. Modern browsers no longer support the technology required for XBAP
apps due to security risks. Plugins that enable XBAPs are no longer supported. For
more information, see Frequently asked questions about WPF browser-hosted
applications (XBAP).
These capabilities are implemented by the Application class, which you add to your
applications using an application definition.
A key component of the support for WPF non-executable data files is the ability to identify and
load them using a unique URI. For more information, see Pack URIs in WPF.
Configuring window appearance (for example, size, location, icons, title bar text, border).
For convenience, and the benefits of reusability and a consistent user experience across
applications, WPF exposes three of the common Windows dialog boxes: OpenFileDialog,
SaveFileDialog, and PrintDialog.
A message box is a special type of dialog box for showing important textual information to
users, and for asking simple Yes/No/OK/Cancel questions. You use the MessageBox class to
create and show message boxes.
Navigation
WPF supports Web-style navigation using pages (Page) and hyperlinks (Hyperlink). Navigation
can be implemented in a variety of ways that include the following:
Pages that are hosted by a frame (Frame), which may be hosted in a standalone page, or
a page compiled into either an XBAP or a standalone application.
NavigationService, the shared navigation engine for processing navigation requests that
is used by Frame, NavigationWindow, and XBAPs to support intra-application navigation.
Remembering back and forward navigation using a journal, which can also be inspected
and manipulated.
WPF also supports a special type of navigation known as structured navigation. Structured
navigation can be used to call one or more pages that return data in a structured and
predictable way that is consistent with calling functions. This capability depends on the
PageFunction<T> class, which is described further in Structured Navigation Overview.
PageFunction<T> also serves to simplify the creation of complex navigation topologies, which
are described in Navigation Topologies Overview.
Hosting
XBAPs can be hosted in Microsoft Internet Explorer or Firefox. Each hosting model has its own
set of considerations and constraints that are covered in Hosting.
Depending on the type of application you build, there are one or more deployment options to
choose from. For more information, see Deploying a WPF Application.
Related Topics
ノ Expand table
Title Description
Windows in WPF Provides details of managing windows in your application including how
to use the Window class and dialog boxes.
Build and Deploy Describes how to build and deploy your WPF application.
Walkthrough: My first WPF A walkthrough that shows how to create a WPF application using page
desktop application navigation, layout, controls, images, styles, and binding.
Application Management Overview
Article • 05/07/2025
All applications tend to share a common set of functionality that applies to application
implementation and management. This topic provides an overview of the functionality in the
Application class for creating and managing applications.
ノ Expand table
Task Approach
Get arguments from the command Handle the Application.Startup event and use the
line StartupEventArgs.Args property. For an example, see the
Application.Startup event.
Get and set the application exit Set the ExitEventArgs.ApplicationExitCode property in the
code Application.Exit event handler or call the Shutdown method and
pass in an integer.
Get and save an application's state See Persist and Restore Application-Scope Properties Across
Application Sessions.
Manage non-code data files, See WPF Application Resource, Content, and Data Files.
including resource files, content
files, and site-of-origin files.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App" />
C#
using System.Windows;
namespace SDKSample
{
public partial class App : Application { }
}
To allow a markup file and code-behind file to work together, the following needs to happen:
In markup, the Application element must include the x:Class attribute. When the
application is built, the existence of x:Class in the markup file causes MSBuild to create a
partial class that derives from Application and has the name that is specified by the
x:Class attribute. This requires the addition of an XML namespace declaration for the
In code-behind, the class must be a partial class with the same name that is specified by
the x:Class attribute in markup and must derive from Application. This allows the code-
behind file to be associated with the partial class that is generated for the markup file
when the application is built (see Building a WPF Application).
7 Note
When you create a new WPF Application project or WPF Browser Application project using
Visual Studio, an application definition is included by default and is defined using both
markup and code-behind.
This code is the minimum that is required to implement an application definition. However, an
additional MSBuild configuration needs to be made to the application definition before
building and running the application.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
Traditionally, developers have needed to write some or all of this code for themselves,
depending on the technology. However, WPF generates this code for you when the markup file
of your application definition is configured as an MSBuild ApplicationDefinition item, as
shown in the following MSBuild project file:
XML
<Project
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ApplicationDefinition Include="App.xaml" />
<Compile Include="App.xaml.cs" />
...
</Project>
Because the code-behind file contains code, it is marked as an MSBuild Compile item, as is
normal.
The application of these MSBuild configurations to the markup and code-behind files of an
application definition causes MSBuild to generate code like the following:
C#
using System;
using System.Windows;
namespace SDKSample
{
public class App : Application
{
public App() { }
[STAThread]
public static void Main()
{
// Create new instance of application subclass
App app = new App();
The resulting code augments your application definition with additional infrastructure code,
which includes the entry-point method Main . The STAThreadAttribute attribute is applied to
the Main method to indicate that the main UI thread for the WPF application is an STA thread,
which is required for WPF applications. When called, Main creates a new instance of App before
calling the InitializeComponent method to register the events and set the properties that are
implemented in markup. Because InitializeComponent is generated for you, you don't need to
explicitly call InitializeComponent from an application definition like you do for Page and
Window implementations. Finally, the Run method is called to start the application.
The following code shows how to acquire a reference to the Application object for the current
AppDomain.
C#
C#
You can inspect the value of Current at any point in the lifetime of an Application object.
However, you should be careful. After the Application class is instantiated, there is a period
during which the state of the Application object is inconsistent. During this period, Application
is performing the various initialization tasks that are required by your code to run, including
establishing application infrastructure, setting properties, and registering events. If you try to
use the Application object during this period, your code may have unexpected results,
particularly if it depends on the various Application properties being set.
When Application completes its initialization work, its lifetime truly begins.
Application Lifetime
The lifetime of a WPF application is marked by several events that are raised by Application to
let you know when your application has started, has been activated and deactivated, and has
been shut down.
Splash Screen
Starting in the .NET Framework 3.5 SP1, you can specify an image to be used in a startup
window, or splash screen. The SplashScreen class makes it easy to display a startup window
while your application is loading. The SplashScreen window is created and shown before Run is
called. For more information, see Application Startup Time and Add a Splash Screen to a WPF
Application.
Starting an Application
After Run is called and the application is initialized, the application is ready to run. This
moment is signified when the Startup event is raised:
C#
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
}
}
}
At this point in an application's lifetime, the most common thing to do is to show a UI.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
Startup="App_Startup" />
C#
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Open a window
MainWindow window = new MainWindow();
window.Show();
}
}
}
7 Note
The first Window to be instantiated in a standalone application becomes the main
application window by default. This Window object is referenced by the
Application.MainWindow property. The value of the MainWindow property can be
changed programmatically if a different window than the first instantiated Window should
be the main window.
When an XBAP first starts, it will most likely navigate to a Page. This is shown in the following
code.
XAML
<Application
x:Class="SDKSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_Startup" />
C#
using System;
using System.Windows;
using System.Windows.Navigation;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
((NavigationWindow)this.MainWindow).Navigate(new Uri("HomePage.xaml",
UriKind.Relative));
}
}
}
If you handle Startup to only open a Window or navigate to a Page, you can set the StartupUri
attribute in markup instead.
The following example shows how to use the StartupUri from a standalone application to open
a Window.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
The following example shows how to use StartupUri from an XBAP to navigate to a Page.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />
This markup has the same effect as the previous code for opening a window.
7 Note
You need to handle the Startup event to open a Window if you need to instantiate it using a
non-parameterless constructor, or you need to set its properties or subscribe to its events
before showing it, or you need to process any command-line arguments that were supplied
when the application was launched.
wpfapplication.exe /StartMinimized
During application initialization, WPF retrieves the command-line arguments from the
operating system and passes them to the Startup event handler via the Args property of the
StartupEventArgs parameter. You can retrieve and store the command-line arguments using
code like the following.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
Startup="App_Startup" />
C#
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
// Process command line args
bool startMinimized = false;
for (int i = 0; i != e.Args.Length; ++i)
{
if (e.Args[i] == "/StartMinimized")
{
startMinimized = true;
}
}
The code handles Startup to check whether the /StartMinimized command-line argument was
provided; if so, it opens the main window with a WindowState of Minimized. Note that because
the WindowState property must be set programmatically, the main Window must be opened
explicitly in code.
XBAPs cannot retrieve and process command-line arguments because they are launched using
ClickOnce deployment (see Deploying a WPF Application). However, they can retrieve and
process query string parameters from the URLs that are used to launch them.
You can detect when an application becomes active by handling the Application.Activated
event.
You can detect when an application becomes inactive by handling the Application.Deactivated
event.
The following code shows how to handle the Activated and Deactivated events to determine
whether an application is active.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Activated="App_Activated"
Deactivated="App_Deactivated" />
C#
using System;
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
bool isApplicationActive;
7 Note
Application Shutdown
The life of an application ends when it is shut down, which can occur for the following reasons:
To help you manage application shutdown, Application provides the Shutdown method, the
ShutdownMode property, and the SessionEnding and Exit events.
7 Note
Shutdown can only be called from applications that have UIPermission. Standalone WPF
applications always have this permission. However, XBAPs running in the Internet zone
partial-trust security sandbox do not.
Shutdown Mode
Most applications shut down either when all the windows are closed or when the main window
is closed. Sometimes, however, other application-specific conditions may determine when an
application shuts down. You can specify the conditions under which your application will shut
down by setting ShutdownMode with one of the following ShutdownMode enumeration
values:
OnLastWindowClose
OnMainWindowClose
OnExplicitShutdown
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
ShutdownMode="OnMainWindowClose" />
7 Note
ShutdownMode can be set from an XBAP, but it is ignored; an XBAP is always shut down
when it is navigated away from in a browser or when the browser that hosts the XBAP is
closed. For more information, see Navigation Overview.
Session Ending
The shutdown conditions that are described by the ShutdownMode property are specific to an
application. In some cases, though, an application may shut down as a result of an external
condition. The most common external condition occurs when a user ends the Windows session
by the following actions:
Logging off
Shutting down
Restarting
Hibernating
To detect when a Windows session ends, you can handle the SessionEnding event, as illustrated
in the following example.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
SessionEnding="App_SessionEnding" />
C#
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
// Ask the user if they want to allow the session to end
string msg = string.Format("{0}. End session?",
e.ReasonSessionEnding);
MessageBoxResult result = MessageBox.Show(msg, "Session Ending",
MessageBoxButton.YesNo);
In this example, the code inspects the ReasonSessionEnding property to determine how the
Windows session is ending. It uses this value to display a confirmation message to the user. If
the user does not want the session to end, the code sets Cancel to true to prevent the
Windows session from ending.
7 Note
Exit
When an application shuts down, it may need to perform some final processing, such as
persisting application state. For these situations, you can handle the Exit event, as the App_Exit
event handler does in the following example. It is defined as an event handler in the App.xaml
file. Its implementation is highlighted in the App.xaml.cs and Application.xaml.vb files.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Exit="App_Exit">
<Application.Resources>
<SolidColorBrush x:Key="ApplicationScopeResource" Color="White">
</SolidColorBrush>
</Application.Resources>
</Application>
C#
using System.Windows;
using System.IO;
using System.IO.IsolatedStorage;
namespace SDKSample
{
public partial class App : Application
{
string filename = "App.txt";
public App()
{
// Initialize application-scope property
this.Properties["NumberOfAppSessions"] = 0;
}
For the complete example, see Persist and Restore Application-Scope Properties Across
Application Sessions.
Exit can be handled by both standalone applications and XBAPs. For XBAPs, Exit is raised when
in the following circumstances:
In Internet Explorer, when the tab that is hosting the XBAP is closed.
Exit Code
Applications are mostly launched by the operating system in response to a user request.
However, an application can be launched by another application to perform some specific task.
When the launched application shuts down, the launching application may want to know the
condition under which the launched application shut down. In these situations, Windows allows
applications to return an application exit code on shutdown. By default, WPF applications
return an exit code value of 0.
7 Note
When you debug from Visual Studio, the application exit code is displayed in the Output
window when the application shuts down, in a message that looks like the following:
The program '[5340] AWPFApp.vshost.exe: Managed' has exited with code 0 (0x0).
You open the Output window by clicking Output on the View menu.
To change the exit code, you can call the Shutdown(Int32) overload, which accepts an integer
argument to be the exit code:
C#
You can detect the value of the exit code, and change it, by handling the Exit event. The Exit
event handler is passed an ExitEventArgs which provides access to the exit code with the
ApplicationExitCode property. For more information, see Exit.
7 Note
You can set the exit code in both standalone applications and XBAPs. However, the exit
code value is ignored for XBAPs.
Unhandled Exceptions
Sometimes an application may shut down under abnormal conditions, such as when an
unanticipated exception is thrown. In this case, the application may not have the code to detect
and process the exception. This type of exception is an unhandled exception; a notification
similar to that shown in the following figure is displayed before the application is closed.
From the user experience perspective, it is better for an application to avoid this default
behavior by doing some or all of the following:
Implementing this support depends on being able to detect unhandled exceptions, which is
what the DispatcherUnhandledException event is raised for.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException" />
C#
using System.Windows;
using System.Windows.Threading;
namespace SDKSample
{
public partial class App : Application
{
void App_DispatcherUnhandledException(object sender,
DispatcherUnhandledExceptionEventArgs e)
{
// Process unhandled exception
See also
Application
WPF Windows Overview
Navigation Overview
WPF Application Resource, Content, and Data Files
Pack URIs in WPF
Application Model: How-to Topics
Application Development
WPF Application Resource, Content, and
Data Files
Article • 05/07/2025
Microsoft Windows applications often depend on files that contain non-executable data, such
as Extensible Application Markup Language (XAML), images, video, and audio. Windows
Presentation Foundation (WPF) offers special support for configuring, identifying, and using
these types of data files, which are called application data files. This support revolves around a
specific set of application data file types, including:
Resource Files: Data files that are compiled into either an executable or library WPF
assembly.
Content Files: Standalone data files that have an explicit association with an executable
WPF assembly.
Site of Origin Files: Standalone data files that have no association with an executable
WPF assembly.
One important distinction to make between these three types of files is that resource files and
content files are known at build time; an assembly has explicit knowledge of them. For site of
origin files, however, an assembly may have no knowledge of them at all, or implicit knowledge
through a pack uniform resource identifier (URI) reference; the case of the latter, there is no
guarantee that the referenced site of origin file actually exists.
To reference application data files, Windows Presentation Foundation (WPF) uses the Pack
uniform resource identifier (URI) Scheme, which is described in detail in Pack URIs in WPF).
This topic describes how to configure and use application data files.
Resource Files
If an application data file must always be available to an application, the only way to guarantee
availability is to compile it into an application's main executable assembly or one of its
referenced assemblies. This type of application data file is known as a resource file.
You don't need to update the resource file's content after it is compiled into an assembly.
You want to simplify application distribution complexity by reducing the number of file
dependencies.
Your application data file needs to be localizable (see WPF Globalization and Localization
Overview).
7 Note
The resource files described in this section are different than the resource files described
in XAML Resources and different than the embedded or linked resources described in
Manage Application Resources (.NET).
XML
7 Note
In Visual Studio, you create a resource file by adding a file to a project and setting its
Build Action to Resource .
When the project is built, MSBuild compiles the resource into the assembly.
As an example, the following code shows how to use GetResourceStream to load a Page
resource file and set it as the content of a Frame ( pageFrame ):
C#
// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
While calling GetResourceStream gives you access to the Stream, you need to perform the
additional work of converting it to the type of the property that you'll be setting it with.
Instead, you can let WPF take care of opening and converting the Stream by loading a resource
file directly into the property of a type using code.
The following example shows how to load a Page directly into a Frame ( pageFrame ) using code.
C#
XAML
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="SOOPage.xaml" />
You can do this when a XAML file is included in an MSBuild project as a Page item.
XML
7 Note
When a project with Page items is compiled, the XAML items are converted to binary format
and compiled into the associated assembly. Consequently, these files can be used in the same
way as typical resource files.
7 Note
If a XAML file is configured as a Resource item, and does not have a code-behind file, the
raw XAML is compiled into an assembly rather than a binary version of the raw XAML.
Content Files
A content file is distributed as a loose file alongside an executable assembly. Although they are
not compiled into an assembly, assemblies are compiled with metadata that establishes an
association with each content file.
You should use content files when your application requires a specific set of application data
files that you want to be able to update without recompiling the assembly that consumes
them.
XML
7 Note
In Visual Studio, you create a content file by adding a file to a project and setting its Build
Action to Content , and set its Copy to Output Directory to Copy always (same as Always )
[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]
The value of the AssemblyAssociatedContentFileAttribute implies the path to the content file
relative to its position in the project. For example, if a content file was located in a project
subfolder, the additional path information would be incorporated into the
AssemblyAssociatedContentFileAttribute value.
[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]
The AssemblyAssociatedContentFileAttribute value is also the value of the path to the content
file in the build output folder.
C#
While calling GetContentStream gives you access to the Stream, you need to perform the
additional work of converting it to the type of the property that you'll be setting it with.
Instead, you can let WPF take care of opening and converting the Stream by loading a resource
file directly into the property of a type using code.
The following example shows how to load a Page directly into a Frame ( pageFrame ) using code.
C#
XAML
You don't know what files your assembly will require until run time.
You want to be able to update files without recompiling the assembly that they are
associated with.
Your application uses large data files, such as audio and video, and you only want users to
download them if they choose to.
It is possible to load these types of files by using traditional URI schemes, such as the file:///
and http:// schemes.
XAML
However, the file:/// and http:// schemes require your application to have full trust. If your
application is a XAML browser application (XBAP) that was launched from the Internet or
intranet, and it requests only the set of permissions that are allowed for applications launched
from those locations, loose files can only be loaded from the application's site of origin (launch
location). Such files are known as site of origin files.
Site of origin files are the only option for partial trust applications, although are not limited to
partial trust applications. Full trust applications may still need to load application data files that
they do not know about at build time; while full trust applications could use file:///, it is likely
that the application data files will be installed in the same folder as, or a subfolder of, the
application assembly. In this case, using site of origin referencing is easier than using file:///,
because using file:/// requires you to work out the full path the file.
7 Note
Site of origin files are not cached with an XAML browser application (XBAP) on a client
machine, while content files are. Consequently, they are only downloaded when
specifically requested. If an XAML browser application (XBAP) application has large media
files, configuring them as site of origin files means the initial application launch is much
faster, and the files are only downloaded on demand.
If you do know at compile time the files that you would like to be located at the site of origin,
but still want to avoid an explicit dependency, you can add those files to an MSBuild project as
None item. As with content files, you need to set the MSBuild CopyToOutputDirectory attribute
to specify that the site of origin file is copied to a location that is relative to the built assembly,
by specifying either the Always value or the PreserveNewest value.
XML
7 Note
In Visual Studio, you create a site of origin file by adding a file to a project and setting its
Build Action to None .
When the project is built, MSBuild copies the specified files to the build output folder.
As an example, the following code shows how to use GetRemoteStream to load a Page site of
origin file and set it as the content of a Frame ( pageFrame ).
C#
While calling GetRemoteStream gives you access to the Stream, you need to perform the
additional work of converting it to the type of the property that you'll be setting it with.
Instead, you can let WPF take care of opening and converting the Stream by loading a resource
file directly into the property of a type using code.
The following example shows how to load a Page directly into a Frame ( pageFrame ) using code.
C#
XAML
See also
Pack URIs in WPF
Pack URIs in WPF
Article • 05/07/2025
In Windows Presentation Foundation (WPF), uniform resource identifiers (URIs) are used to
identify and load files in many ways, including the following:
Specifying the user interface (UI) to show when an application first starts.
Loading images.
Navigating to pages.
Furthermore, URIs can be used to identify and load files from a variety of locations, including
the following:
A referenced assembly.
To provide a consistent mechanism for identifying and loading these types of files from these
locations, WPF leverages the extensibility of the pack URI scheme. This topic provides an
overview of the scheme, covers how to construct pack URIs for a variety of scenarios, discusses
absolute and relative URIs and URI resolution, before showing how to use pack URIs from both
markup and code.
The scheme that is specified by a URI is defined by its prefix; http, ftp, and file are well-known
examples. The pack URI scheme uses "pack" as its scheme, and contains two components:
authority and path. The following is the format for a pack URI.
pack://authority/path
The authority specifies the type of package that a part is contained by, while the path specifies
the location of a part within a package.
Packages and parts are analogous to applications and files, where an application (package) can
include one or more files (parts), including:
Content files.
To access these types of files, WPF supports two authorities: application:/// and siteoforigin:///.
The application:/// authority identifies application data files that are known at compile time,
including resource and content files. The siteoforigin:/// authority identifies site of origin files.
The scope of each authority is shown in the following figure.
7 Note
The authority component of a pack URI is an embedded URI that points to a package and
must conform to RFC 2396. Additionally, the "/" character must be replaced with the ","
character, and reserved characters such as "%" and "?" must be escaped. See the OPC for
details.
The following sections explain how to construct pack URIs using these two authorities in
conjunction with the appropriate paths for identifying resource, content, and site of origin files.
Authority: application:///.
Path: The name of the resource file, including its path, relative to the local assembly
project folder root.
The following example shows the pack URI for a XAML resource file that is located in the root
of the local assembly's project folder.
pack://application:,,,/ResourceFile.xaml
The following example shows the pack URI for a XAML resource file that is located in a
subfolder of the local assembly's project folder.
pack://application:,,,/Subfolder/ResourceFile.xaml
Authority: application:///.
Path: The name of a resource file that is compiled into a referenced assembly. The path
must conform to the following format:
AssemblyShortName{;Version]{;PublicKey];component/Path
;Version [optional]: the version of the referenced assembly that contains the resource
file. This is used when two or more referenced assemblies with the same short name
are loaded.
;PublicKey [optional]: the public key that was used to sign the referenced assembly.
This is used when two or more referenced assemblies with the same short name are
loaded.
;component: specifies that the assembly being referred to is referenced from the local
assembly.
/Path: the name of the resource file, including its path, relative to the root of the
referenced assembly's project folder.
The following example shows the pack URI for a XAML resource file that is located in the root
of the referenced assembly's project folder.
pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml
The following example shows the pack URI for a XAML resource file that is located in a
subfolder of the referenced assembly's project folder.
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml
The following example shows the pack URI for a XAML resource file that is located in the root
folder of a referenced, version-specific assembly's project folder.
pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml
Note that the pack URI syntax for referenced assembly resource files can be used only with the
application:/// authority. For example, the following is not supported in WPF.
pack://siteoforigin:,,,/SomeAssembly;component/ResourceFile.xaml
Authority: application:///.
Path: The name of the content file, including its path relative to the file system location of
the application's main executable assembly.
The following example shows the pack URI for a XAML content file, located in the same folder
as the executable assembly.
pack://application:,,,/ContentFile.xaml
The following example shows the pack URI for a XAML content file, located in a subfolder that
is relative to the application's executable assembly.
pack://application:,,,/Subfolder/ContentFile.xaml
7 Note
HTML content files cannot be navigated to. The URI scheme only supports navigation to
HTML files that are located at the site of origin.
Authority: siteoforigin:///.
Path: The name of the site of origin file, including its path relative to the location from
which the executable assembly was launched.
The following example shows the pack URI for a XAML site of origin file, stored in the location
from which the executable assembly is launched.
pack://siteoforigin:,,,/SiteOfOriginFile.xaml
The following example shows the pack URI for a XAML site of origin file, stored in subfolder
that is relative to the location from which the application's executable assembly is launched.
pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml
Page Files
XAML files that are configured as MSBuild Page items are compiled into assemblies in the
same way as resource files. Consequently, MSBuild Page items can be identified using pack
URIs for resource files.
The types of XAML files that are commonly configured as MSBuild Page items have one of the
following as their root element:
System.Windows.Window
System.Windows.Controls.Page
System.Windows.Navigation.PageFunction<T>
System.Windows.ResourceDictionary
System.Windows.Documents.FlowDocument
System.Windows.Controls.UserControl
For example, consider the following absolute pack URI for a resource file in the local assembly.
pack://application:,,,/ResourceFile.xaml
The relative pack URI that refers to this resource file would be the following.
/ResourceFile.xaml
7 Note
Because site of origin files are not associated with assemblies, they can only be referred to
with absolute pack URIs.
By default, a relative pack URI is considered relative to the location of the markup or code that
contains the reference. If a leading backslash is used, however, the relative pack URI reference
is then considered relative to the root of the application. For example, consider the following
project structure.
App.xaml
Page2.xaml
\SubFolder
+ Page1.xaml
+ Page2.xaml
If Page1.xaml contains a URI that references Root\SubFolder\Page2.xaml, the reference can use
the following relative pack URI.
Page2.xaml
If Page1.xaml contains a URI that references Root\Page2.xaml, the reference can use the
following relative pack URI.
/Page2.xaml
pack://application:,,,/ResourceOrContentFile.xaml
This absolute pack URI could refer to either a resource file in the local assembly or a content
file. The same is true for the following relative URI.
/ResourceOrContentFile.xaml
In order to determine the type of file that a pack URI refers to, WPF resolves URIs for resource
files in local assemblies and content files by using the following heuristics:
1. Probe the assembly metadata for an AssemblyAssociatedContentFileAttribute attribute
that matches the pack URI.
4. If a resource file that matches the path of the pack URI is found, the path of the pack URI
refers to a resource file.
URI resolution does not apply for URIs that refer to the following:
Content files in referenced assemblies: these file types are not supported by WPF.
Embedded files in referenced assemblies: URIs that identify them are unique because they
include both the name of the referenced assembly and the ;component suffix.
Site of origin files: URIs that identify them are unique because they are the only files that
can be identified by pack URIs that contain the siteoforigin:/// authority.
One simplification that pack URI resolution allows is for code to be somewhat independent of
the locations of resource and content files. For example, if you have a resource file in the local
assembly that is reconfigured to be a content file, the pack URI for the resource remains the
same, as does the code that uses the pack URI.
Application.StartupUri
Frame.Source
NavigationWindow.Source
Hyperlink.NavigateUri
Window.Icon
Image.Source
These properties can be set from both markup and code. This section demonstrates the basic
constructions for both and then shows examples of common scenarios.
Table 1 illustrates the various absolute pack URIs that you can specify in markup.
ノ Expand table
ノ Expand table
C#
By default, the Uri class considers pack URIs to be absolute. Consequently, an exception is
raised when an instance of the Uri class is created with a relative pack URI.
C#
Fortunately, the Uri(String, UriKind) overload of the Uri class constructor accepts a parameter of
type UriKind to allow you to specify whether a pack URI is either absolute or relative.
C#
You should specify only Absolute or Relative when you are certain that the provided pack URI is
one or the other. If you don't know the type of pack URI that is used, such as when a user
enters a pack URI at run time, use RelativeOrAbsolute instead.
C#
Table 3 illustrates the various relative pack URIs that you can specify in code by using
System.Uri.
ノ Expand table
referenced
assembly
Table 4 illustrates the various relative pack URIs that you can specify in code using System.Uri.
ノ Expand table
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
Standalone applications and XAML browser applications (XBAPs) can also specify a page as the
initial UI, as shown in the following example.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />
If the application is a standalone application and a page is specified with StartupUri, WPF
opens a NavigationWindow to host the page. For XBAPs, the page is shown in the host
browser.
Navigating to a Page
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page With Hyperlink"
WindowWidth="250"
WindowHeight="250">
XAML
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
Navigate to Another Page
</Hyperlink>
XAML
</Page>
For more information on the various ways to navigate in WPF, see Navigation Overview.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MainWindow"
Icon="WPFIcon1.ico">
</Window>
WPF allows applications to use a wide variety of media types, all of which can be identified and
loaded with pack URIs, as shown in the following examples.
XAML
XAML
XAML
For more information on working with media content, see Graphics and Multimedia.
Loading a Resource Dictionary from the Site of Origin
Resource dictionaries (ResourceDictionary) can be used to support application themes. One
way to create and manage themes is to create multiple themes as resource dictionaries that are
located at an application's site of origin. This allows themes to be added and updated without
recompiling and redeploying an application. These resource dictionaries can be identified and
loaded using pack URIs, which is shown in the following example.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml">
<Application.Resources>
<ResourceDictionary Source="pack://siteoforigin:,,,/PageTheme.xaml" />
</Application.Resources>
</Application>
See also
WPF Application Resource, Content, and Data Files
How to: Add a Splash Screen to a WPF
Application
Article • 05/07/2025
This topic shows how to add a startup window, or splash screen, to a Windows Presentation
Foundation (WPF) application.
4. In the Properties window, click the drop-down arrow for the Build Action property.
The splash screen image appears in the center of the screen, and then fades when the
main application window appears.
See also
SplashScreen
How to: Add Existing Items to a Project
How to: Use an Application-Scope
Resource Dictionary
Article • 05/07/2025
This example shows how to define and use an application-scope custom resource dictionary.
Example
Application exposes an application-scope store for shared resources: Resources. By default, the
Resources property is initialized with an instance of the ResourceDictionary type. You use this
instance when you get and set application-scope properties using Resources. For more
information, see How to: Get and Set an Application-Scope Resource.
If you have multiple resources that you set using Resources, you can instead use a custom
resource dictionary to store those resources and set Resources with it instead. The following
shows how you declare a custom resource dictionary using XAML.
XAML
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<SolidColorBrush x:Key="StandardSolidColorBrush" Color="Blue" />
<LinearGradientBrush x:Key="StandardLinearGradientBrush" StartPoint="0.0,0.0"
EndPoint="1.0,1.0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</ResourceDictionary>
Swapping entire resource dictionaries using Resources allows you to support application-scope
themes, where each theme is encapsulated by a single resource dictionary. The following
example shows how to set the ResourceDictionary.
XAML
XAML
The following shows how you can also get the resources in code.
C#
There are two considerations to make when using Resources. First, the dictionary key is an
object, so you must use exactly the same object instance when both setting and getting a
property value. (Note that the key is case-sensitive when using a string.) Second, the dictionary
value is an object, so you will have to convert the value to the desired type when getting a
property value.
Some resource types may automatically use a property defined by the type as an explicit key,
such as the Style and DataTemplate types. This may override your x:Key value. To guarantee
that your x:Key key is respected, declare it before the explicit key property. For more
information, see Styles, DataTemplates, and implicit keys.
See also
ResourceDictionary
Resources
XAML Resources
Merged Resource Dictionaries
How to: Persist and Restore Application-
Scope Properties Across Application
Sessions
Article • 05/07/2025
This example shows how to persist application-scope properties when an application shuts
down, and how to restore application-scope properties when an application is next launched.
Example
The application persists application-scope properties to, and restores them from, isolated
storage. Isolated storage is a protected storage area that can safely be used by applications
without file access permission. The App.xaml file defines the App_Startup method as the
handler for the Application.Startup event, and the App_Exit method as the handler for the
Application.Exit event, as shown in the highlighted lines of the following XAML:
7 Note
The following XAML is written for CSharp. The Visual Basic version omits the class
declaration.
XAML
<Application x:Class="SDKSamples.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Exit="App_Exit">
</Application>
This next example shows the Application code-behind, which contains the event handlers for
the XAML. The App_Startup method restores application-scope properties, and the App_Exit
method saves application-scope properties.
C#
using System.IO.IsolatedStorage;
using System.IO;
using System.Windows;
namespace SDKSamples
{
public partial class App : Application
{
string _filename = "App.data";
public App()
{
// Initialize application-scope property
Properties["NumberOfAppSessions"] = "0";
}
}
Windows in WPF Applications
Article • 05/07/2025
Users interact with applications through windows. The fundamental purpose of a window is to
host and display content. The type of content that a window hosts depends on the type of data
that an application operates over, which can include media, Extensible Application Markup
Language (XAML) pages, Web pages, documents, database tables and records, and system
information.
In This Section
WPF Windows Overview Dialog Boxes Overview How-to Topics
Reference
Window
NavigationWindow
Related Sections
Application Management Overview Navigation Overview Hosting Build and Deploy
Overview of WPF windows
Article • 05/07/2025
Users interact with Windows Presentation Foundation (WPF) applications through windows.
The primary purpose of a window is to host content that visualizes data and enables users to
interact with data. WPF applications provide their own windows by using the Window class.
This article introduces Window before covering the fundamentals of creating and managing
windows in applications.
) Important
This article uses XAML generated from a C# project. If you're using Visual Basic, the XAML
may look slightly different. These differences are typically present on x:Class attribute
values. C# includes the root namespace for the project while Visual Basic doesn't.
The project templates for C# create an App type contained in the app.xaml file. In Visual
Basic, the type is named Application and the file is named Application.xaml .
Display a window.
Configure the size, position, and appearance of a window.
Host application-specific content.
Manage the lifetime of a window.
The non-client area of a window is implemented by WPF and includes the parts of a window
that are common to most windows, including the following:
The client area of a window is the area within a window's non-client area and is used by
developers to add application-specific content, such as menu bars, tool bars, and controls.
Implementing a window
The implementation of a typical window includes both appearance and behavior, where
appearance defines how a window looks to users and behavior defines the way a window
functions as users interact with it. In WPF, you can implement the appearance and behavior of
a window using either code or XAML markup.
In general, however, the appearance of a window is implemented using XAML markup, and its
behavior is implemented using code-behind, as shown in the following example.
XAML
<Window x:Class="WindowsOverview.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WindowsOverview"
>
</Window>
C#
using System.Windows;
namespace WindowsOverview
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
To enable a XAML markup file and code-behind file to work together, the following are
required:
In markup, the Window element must include the x:Class attribute. When the application
is built, the existence of x:Class attribute causes Microsoft build engine (MSBuild) to
generate a partial class that derives from Window with the name that is specified by the
x:Class attribute. This requires the addition of an XML namespace declaration for the
the events and set the properties that are implemented in markup.
In code-behind, the class must be a partial class with the same name that is specified by
the x:Class attribute in markup, and it must derive from Window. This allows the code-
behind file to be associated with the partial class that is generated for the markup file
when the application is built, for more information, see Compile a WPF Application.
In code-behind, the Window class must implement a constructor that calls the
InitializeComponent method. InitializeComponent is implemented by the markup file's
generated partial class to register events and set properties that are defined in markup.
7 Note
When you add a new Window to your project by using Visual Studio, the Window is
implemented using both markup and code-behind, and includes the necessary
configuration to create the association between the markup and code-behind files as
described here.
With this configuration in place, you can focus on defining the appearance of the window in
XAML markup and implementing its behavior in code-behind. The following example shows a
window with a button that defines an event handler for the Click event. This is implemented in
the XAML and the handler is implemented in code-behind.
XAML
<Window x:Class="WindowsOverview.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WindowsOverview"
>
</Window>
C#
using System.Windows;
namespace WindowsOverview
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
.NET SDK projects automatically import the correct Page and Compile items for you, and you
don't need to declare these. When the project is configured for WPF, the XAML markup files
are automatically imported as Page items, and the corresponding code-behind file is imported
as Compile .
MSBuild projects won't automatically import the types and you must declare them yourself:
XML
<Project>
...
<Page Include="MarkupAndCodeBehindWindow.xaml" />
<Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" />
...
</Project>
For information about building WPF applications, see Compile a WPF Application.
Window lifetime
As with any class, a window has a lifetime that begins when it's first instantiated, after which it's
opened, activated/deactivated, and eventually closed.
Opening a window
To open a window, you first create an instance of it, which is demonstrated in the following
example:
C#
using System.Windows;
namespace WindowsOverview
{
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
// Create the window
Window1 window = new Window1();
In this example Window1 is instantiated when the application starts, which occurs when the
Startup event is raised. For more information about the startup window, see How to get or set
the main application window.
When a window is instantiated, a reference to it's automatically added to a list of windows that
is managed by the Application object. The first window to be instantiated is automatically set
by Application as the main application window.
The window is finally opened by calling the Show method as shown in the following image:
A window that is opened by calling Show is a modeless window, and the application doesn't
prevent users from interacting with other windows in the application. Opening a window with
ShowDialog opens a window as modal and restricts user interaction to the specific window. For
more information, see Dialog Boxes Overview.
When Show is called, a window does initialization work before it's shown to establish
infrastructure that allows it to receive user input. When the window is initialized, the
SourceInitialized event is raised and the window is shown.
For more information, see How to open a window or dialog box.
Startup window
The previous example used the Startup event to run code that displayed the initial application
window. As a shortcut, instead use StartupUri to specify the path to a XAML file in your
application. The application automatically creates and displays the window specified by that
property.
XAML
<Application x:Class="WindowsOverview.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WindowsOverview"
StartupUri="ClippedWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
Window ownership
A window that is opened by using the Show method doesn't have an implicit relationship with
the window that created it. Users can interact with either window independently of the other,
which means that either window can do the following:
Cover the other (unless one of the windows has its Topmost property set to true ).
Be minimized, maximized, and restored without affecting the other.
Some windows require a relationship with the window that opens them. For example, an
Integrated Development Environment (IDE) application may open property windows and tool
windows whose typical behavior is to cover the window that creates them. Furthermore, such
windows should always close, minimize, maximize, and restore in concert with the window that
created them. Such a relationship can be established by making one window own another, and
is achieved by setting the Owner property of the owned window with a reference to the owner
window. This is shown in the following example.
C#
The owned window can reference its owner window by inspecting the value of its Owner
property.
The owner window can discover all the windows it owns by inspecting the value of its
OwnedWindows property.
Window activation
When a window is first opened, it becomes the active window. The active window is the window
that is currently capturing user input, such as key strokes and mouse clicks. When a window
becomes active, it raises the Activated event.
7 Note
When a window is first opened, the Loaded and ContentRendered events are raised only
after the Activated event is raised. With this in mind, a window can effectively be
considered opened when ContentRendered is raised.
After a window becomes active, a user can activate another window in the same application, or
activate another application. When that happens, the currently active window becomes
deactivated and raises the Deactivated event. Likewise, when the user selects a currently
deactivated window, the window becomes active again and Activated is raised.
One common reason to handle Activated and Deactivated is to enable and disable functionality
that can only run when a window is active. For example, some windows display interactive
content that requires constant user input or attention, including games and video players. The
following example is a simplified video player that demonstrates how to handle Activated and
Deactivated to implement this behavior.
XAML
<Window x:Class="WindowsOverview.CustomMediaPlayerWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Activated="Window_Activated"
Deactivated="Window_Deactivated"
Title="CustomMediaPlayerWindow" Height="450" Width="800">
<Grid>
<MediaElement x:Name="mediaElement" Stretch="Fill"
LoadedBehavior="Manual" Source="numbers.mp4" />
</Grid>
</Window>
C#
using System;
using System.Windows;
namespace WindowsOverview
{
public partial class CustomMediaPlayerWindow : Window
{
public CustomMediaPlayerWindow() =>
InitializeComponent();
Other types of applications may still run code in the background when a window is
deactivated. For example, a mail client may continue polling the mail server while the user is
using other applications. Applications like these often provide different or extra behavior while
the main window is deactivated. For a mail program, this may mean both adding the new mail
item to the inbox and adding a notification icon to the system tray. A notification icon need
only be displayed when the mail window isn't active, which is determined by inspecting the
IsActive property.
If a background task completes, a window may want to notify the user more urgently by calling
Activate method. If the user is interacting with another application activated when Activate is
called, the window's taskbar button flashes. However, if a user is interacting with the current
application, calling Activate will bring the window to the foreground.
7 Note
You can handle application-scope activation using the Application.Activated and
Application.Deactivated events.
There are scenarios where windows shouldn't be activated when shown, such as conversation
windows of a chat application or notification windows of an email application.
If your application has a window that shouldn't be activated when shown, you can set its
ShowActivated property to false before calling the Show method for the first time. As a
consequence:
The window will become activated, however, as soon as the user activates it by clicking either
the client or non-client area. In this case:
Closing a window
The life of a window starts coming to an end when a user closes it. Once a window is closed, it
can't be reopened. A window can be closed by using elements in the non-client area, including
the following:
You can provide more mechanisms to the client area to close a window, the more common of
which include the following:
An Exit item in the File menu, typically for main application windows.
A Close item in the File menu, typically on a secondary application window.
A Cancel button, typically on a modal dialog box.
A Close button, typically on a modeless dialog box.
To close a window in response to one of these custom mechanisms, you need to call the Close
method. The following example implements the ability to close a window by choosing Exit
from a File menu.
XAML
<Window x:Class="WindowsOverview.ClosingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ClosingWindow" Height="450" Width="800">
<StackPanel>
<Menu>
<MenuItem Header="_File">
<MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
</MenuItem>
</Menu>
</StackPanel>
</Window>
C#
using System.Windows;
namespace WindowsOverview
{
public partial class ClosingWindow : Window
{
public ClosingWindow() =>
InitializeComponent();
7 Note
An application can be configured to shut down automatically when either the main
application window closes (see MainWindow) or the last window closes. For more
information, see ShutdownMode.
While a window can be explicitly closed through mechanisms provided in the non-client and
client areas, a window can also be implicitly closed as a result of behavior in other parts of the
application or Windows, including the following:
) Important
Closing is raised before the window closes, and it provides a mechanism by which window
closure can be prevented. One common reason to prevent window closure is if window content
contains modified data. In this situation, the Closing event can be handled to determine
whether data is dirty and, if so, to ask the user whether to either continue closing the window
without saving the data or to cancel window closure. The following example shows the key
aspects of handling Closing.
XAML
<Window x:Class="WindowsOverview.DataWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataWindow" Height="450" Width="800"
Closing="Window_Closing">
<Grid>
<TextBox x:Name="documentTextBox"
TextChanged="documentTextBox_TextChanged" />
</Grid>
</Window>
C#
using System.Windows;
using System.Windows.Controls;
namespace WindowsOverview
{
public partial class DataWindow : Window
{
private bool _isDataDirty;
The Closing event handler is passed a CancelEventArgs, which implements the Cancel property
that you set to true to prevent a window from closing.
If Closing isn't handled, or it's handled but not canceled, the window will close. Just before a
window actually closes, Closed is raised. At this point, a window can't be prevented from
closing.
Window location
While a window is open, it has a location in the x and y dimensions relative to the desktop. This
location can be determined by inspecting the Left and Top properties, respectively. Set these
properties to change the location of the window.
You can also specify the initial location of a Window when it first appears by setting the
WindowStartupLocation property with one of the following WindowStartupLocation
enumeration values:
CenterOwner (default)
CenterScreen
Manual
If the startup location is specified as Manual, and the Left and Top properties have not been
set, Window will ask the operating system for a location to appear in.
Within each z-order type, the currently active window appears above all other windows in the
same z-order.
Window size
Besides having a desktop location, a window has a size that is determined by several
properties, including the various width and height properties and SizeToContent.
MinWidth, Width, and MaxWidth are used to manage the range of widths that a window can
have during its lifetime.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
MinWidth="300" Width="400" MaxWidth="500">
</Window>
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
MinHeight="300" Height="400" MaxHeight="500">
</Window>
Because the various width values and height values each specify a range, it's possible for the
width and height of a resizable window to be anywhere within the specified range for the
respective dimension. To detect its current width and height, inspect ActualWidth and
ActualHeight, respectively.
If you'd like the width and height of your window to have a size that fits to the size of the
window's content, you can use the SizeToContent property, which has the following values:
SizeToContent.Manual
No effect (default).
SizeToContent.Width
Fit to content width, which has the same effect as setting both MinWidth and MaxWidth
to the width of the content.
SizeToContent.Height
Fit to content height, which has the same effect as setting both MinHeight and
MaxHeight to the height of the content.
SizeToContent.WidthAndHeight
Fit to content width and height, which has the same effect as setting both MinHeight and
MaxHeight to the height of the content, and setting both MinWidth and MaxWidth to the
width of the content.
The following example shows a window that automatically sizes to fit its content, both vertically
and horizontally, when first shown.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
SizeToContent="WidthAndHeight">
</Window>
The following example shows how to set the SizeToContent property in code to specify how a
window resizes to fit its content .
C#
1. FrameworkElement.MinHeight
2. FrameworkElement.MaxHeight
3. SizeToContent.Height / SizeToContent.WidthAndHeight
4. FrameworkElement.Height
1. FrameworkElement.MinWidth
2. FrameworkElement.MaxWidth
3. SizeToContent.Width / SizeToContent.WidthAndHeight
4. FrameworkElement.Width
The order of precedence can also determine the size of a window when it's maximized, which is
managed with the WindowState property.
Window state
During the lifetime of a resizable window, it can have three states: normal, minimized, and
maximized. A window with a normal state is the default state of a window. A window with this
state allows a user to move and resize it by using a resize grip or the border, if it's resizable.
A window with a minimized state collapses to its task bar button if ShowInTaskbar is set to
true ; otherwise, it collapses to the smallest possible size it can be and moves itself to the
bottom-left corner of the desktop. Neither type of minimized window can be resized using a
border or resize grip, although a minimized window that isn't shown in the task bar can be
dragged around the desktop.
A window with a maximized state expands to the maximum size it can be, which will only be as
large as its MaxWidth, MaxHeight, and SizeToContent properties dictate. Like a minimized
window, a maximized window can't be resized by using a resize grip or by dragging the border.
7 Note
The values of the Top, Left, Width, and Height properties of a window always represent
the values for the normal state, even when the window is currently maximized or
minimized.
The state of a window can be configured by setting its WindowState property, which can have
one of the following WindowState enumeration values:
Normal (default)
Maximized
Minimized
The following example shows how to create a window that is shown as maximized when it
opens.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowState="Maximized">
</Window>
In general, you should set WindowState to configure the initial state of a window. Once a
resizable window is shown, users can press the minimize, maximize, and restore buttons on the
window's title bar to change the window state.
Window appearance
You change the appearance of the client area of a window by adding window-specific content
to it, such as buttons, labels, and text boxes. To configure the non-client area, Window provides
several properties, which include Icon to set a window's icon and Title to set its title.
You can also change the appearance and behavior of non-client area border by configuring a
window's resize mode, window style, and whether it appears as a button in the desktop task
bar.
Resize mode
Depending on the WindowStyle property, you can control if, and how, users resize the window.
The window style affects the following:
Allow or disallow resizing by dragging the window border with the mouse.
Whether the Minimize, Maximize, and Close buttons appear on the non-client area.
Whether the Minimize, Maximize, and Close buttons are enabled.
You can configure how a window resizes by setting its ResizeMode property, which can be one
of the following ResizeMode enumeration values:
NoResize
CanMinimize
CanResize (default)
CanResizeWithGrip
As with WindowStyle, the resize mode of a window is unlikely to change during its lifetime,
which means that you'll most likely set it from XAML markup.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ResizeMode="CanResizeWithGrip">
</Window>
Note that you can detect whether a window is maximized, minimized, or restored by inspecting
the WindowState property.
Window style
The border that is exposed from the non-client area of a window is suitable for most
applications. However, there are circumstances where different types of borders are needed, or
no borders are needed at all, depending on the type of window.
To control what type of border a window gets, you set its WindowStyle property with one of
the following values of the WindowStyle enumeration:
None
SingleBorderWindow (default)
ThreeDBorderWindow
ToolWindow
affect how the window was drawn, adding a 3D border to the client area. Starting with
Windows 7, the differences between the two styles are minimal.
You can set WindowStyle using either XAML markup or code. Because it's unlikely to change
during the lifetime of a window, you'll most likely configure it using XAML markup.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowStyle="ToolWindow">
</Window>
There are also situations where the border styles that WindowStyle allows you to have aren't
sufficient. For example, you may want to create an application with a non-rectangular border,
like Microsoft Windows Media Player uses.
For example, consider the speech bubble window shown in the following image:
This type of window can be created by setting the WindowStyle property to None, and by
using special support that Window has for transparency.
XAML
<Window x:Class="WindowsOverview.ClippedWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ClippedWindow" SizeToContent="WidthAndHeight"
WindowStyle="None" AllowsTransparency="True" Background="Transparent">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid.Effect>
<DropShadowEffect BlurRadius="10" ShadowDepth="3" Color="LightBlue"/>
</Grid.Effect>
</Grid>
</Window>
This combination of values instructs the window to render transparent. In this state, the
window's non-client area adornment buttons can't be used and you need to provide your own.
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
ShowInTaskbar="False">
</Window>
Dialog boxes are windows that are often used to gather information from a user to complete a
function. For example, when a user wants to open a file, the Open File dialog box is displayed
by an application to get the file name from the user. For more information, see Dialog Boxes
Overview.
See also
Dialog boxes overview
How to open a window or dialog box
How to open a common dialog box
How to open a message box
How to close a window or dialog box
System.Windows.Window
System.Windows.MessageBox
System.Windows.Navigation.NavigationWindow
System.Windows.Application
Dialog boxes overview
Article • 05/07/2025
Windows Presentation Foundation (WPF) provides ways for you to design your own dialog
boxes. Dialog boxes are windows but with a specific intent and user experience. This article
discusses how a dialog box works and what types of dialog boxes you can create and use.
Dialog boxes are used to:
These types of windows are known as dialog boxes. A dialog box can be displayed in two ways:
modal and modeless.
Displaying a modal dialog box to the user is a technique with which the application interrupts
what it was doing until the user closes the dialog box. This generally comes in the form of a
prompt or alert. Other windows in the application can't be interacted with until the dialog box
is closed. Once the modal dialog box is closed, the application continues. The most common
dialog boxes are used to show an open file or save file prompt, displaying the printer dialog, or
messaging the user with some status.
A modeless dialog box doesn't prevent a user from activating other windows while it's open.
For example, if a user wants to find occurrences of a particular word in a document, a main
window will often open a dialog box to ask a user what word they're looking for. Since the
application doesn't want to prevent the user from editing the document, the dialog box
doesn't need to be modal. A modeless dialog box at least provides a Close button to close the
dialog box. Other buttons may be provided to run specific functions, such as a Find Next
button to find the next word in a word search.
With WPF you can create several types of dialog boxes, such as message boxes, common
dialog boxes, and custom dialog boxes. This article discusses each, and the Dialog Box
Sample provides matching examples.
Message boxes
A message box is a dialog box that can be used to display textual information and to allow
users to make decisions with buttons. The following figure shows a message box that asks a
question and provides the user with three buttons to answer the question.
To create a message box, you use the MessageBox class. MessageBox lets you configure the
message box text, title, icon, and buttons.
Since these dialog boxes are provided by the operating system, they're shared among all the
applications that run on the operating system. These dialog boxes provide a consistent user
experience, and are known as common dialog boxes. As a user uses a common dialog box in
one application, they don't need to learn how to use that dialog box in other applications.
WPF encapsulates the open file, save file, open folder, and print common dialog boxes and
exposes them as managed classes for you to use.
To learn more about common dialog boxes, see the following articles:
There are many design considerations to take into account when you create your own dialog
box. Although both an application window and dialog box contain similarities, such as sharing
the same base class, a dialog box is used for a specific purpose. Usually a dialog box is required
when you need to prompt a user for some sort of information or response. Typically the
application will pause while the dialog box (modal) is displayed, restricting access to the rest of
the application. Once the dialog box is closed, the application continues. Confining interactions
to the dialog box alone, though, isn't a requirement.
When a WPF window is closed, it can't be reopened. Custom dialog boxes are WPF windows
and the same rule applies. To learn how to close a window, see How to close a window or
dialog box.
❌ DON'T clutter the dialog window. The dialog experience is for the user to enter some data,
or to make a choice.
✔️CONSIDER adding a Cancel button so that the user can close the window and indicate that
they don't want to continue.
✔️DO set the Cancel button's IsCancel property to true to allow the user to press the ESC
✔️DO set the title of the window to accurately describe what the dialog represents, or what
the user should do with the dialog.
✔️DO set minimum width and height values for the window, preventing the user from resizing
the window too small.
✔️CONSIDER disabling the ability to resize the window if ShowInTaskbar is set to false . You
XAML
<Window x:Class="Dialogs.Margins"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Change Margins"
Closing="Window_Closing"
MinHeight="200"
MinWidth="300"
SizeToContent="WidthAndHeight"
ResizeMode="NoResize"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner"
FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">
<Grid Margin="10">
<Grid.Resources>
<!-- Default settings for controls -->
<Style TargetType="{x:Type Label}">
<Setter Property="Margin" Value="0,3,5,5" />
<Setter Property="Padding" Value="0,0,0,5" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="0,0,0,5" />
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="70" />
<Setter Property="Height" Value="25" />
<Setter Property="Margin" Value="5,0,0,0" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
The above XAML creates a window that looks similar to the following image:
When a menu item or button runs a function that displays a dialog box that doesn't require
user interaction, such as an About dialog box, an ellipsis isn't required.
Menu items
Menu items are a common way to provide users with application actions that are grouped into
related themes. You've probably seen the File menu on many different applications. In a typical
application, the File menu item provides ways to save a file, load a file, and print a file. If the
action is going to display a modal window, the header typically includes an ellipsis as shown in
the following image:
Two of the menu items have an ellipsis: ... . This helps the user identify that when they select
those menu items, a modal window is shown, pausing the application until the user closes it.
This design technique is an easy way for you to communicate to your users what they should
expect.
Buttons
You can follow the same principle described in the Menu items section. Use an ellipsis on the
button text to indicate that when the user presses the button, a modal dialog will appear. In
the following image, there are two buttons and it's easy to understand which button displays a
dialog box:
Return a result
Opening another window, especially a modal dialog box, is a great way to return status and
information to calling code.
Modal dialogs
When a dialog box is shown by calling ShowDialog(), the code that opened the dialog box
waits until the ShowDialog method returns. When the method returns, the code that called it
needs to decide whether to continue processing or stop processing. The user generally
indicates this by pressing an OK or Cancel button on the dialog box.
When the OK button is pressed, ShowDialog should be designed to return true , and the
Cancel button to return false . This is achieved by setting the DialogResult property when the
button is pressed.
C#
The DialogResult property can only be set if the dialog box was displayed with ShowDialog().
When the DialogResult property is set, the dialog box closes.
If a button's IsCancel property is set to true , and the window is opened with ShowDialog(), the
ESC key will close the window and set DialogResult to false .
For more information about closing dialog boxes, see How to close a window or dialog box.
Processing the response
The ShowDialog() returns a boolean value to indicate whether the user accepted or canceled
the dialog box. If you're alerting the user to something, but not requiring they make a decision
or provide data, you can ignore the response. The response can also be inspected by checking
the DialogResult property. The following code shows how to process the response:
C#
if (result == true)
{
// User accepted the dialog box
MessageBox.Show("Your request will be processed.");
}
else
{
// User cancelled the dialog box
MessageBox.Show("Sorry it didn't work out, we'll try again later.");
}
Modeless dialog
To show a dialog box modeless, call Show(). The dialog box should at least provide a Close
button. Other buttons and interactive elements can be provided to run a specific function, such
as a Find Next button to find the next word in a word search.
Because a modeless dialog box doesn't block the calling code from continuing, you must
provide a different way of returning a result. You can do one of the following:
The following example uses the Window.Closed event to display a message box to the user
when the dialog box closes. The message displayed references a property of the closed dialog
box. For more information about closing dialogs boxes, see How to close a window or dialog
box.
C#
var marginsWindow = new Margins();
marginsWindow.Show();
See also
Overview of WPF windows
How to open a window or dialog box
How to open a common dialog box
How to open a message box
How to close a window or dialog box
Dialog Box Sample
System.Windows.Window
System.Windows.MessageBox
Window Management How-to Topics
Article • 05/07/2025
The following topics show how to manage Windows Presentation Foundation (WPF) windows.
In This Section
Automatically Size a Window to Fit Its Content Get all Windows in an Application Get and Set
the Main Application Window Open a Dialog Box Open a Message Box Open a Window
Related Sections
Application Management Overview
Navigation Overview
Hosting
A message box is a dialog box that is used to quickly display information and optionally allow
users to make decisions. Access to the message box is provided by the MessageBox class. A
message box is displayed modally. And the code that displays the message box is paused until
the user closes the message box either with the close button or a response button.
For presenting or gathering complex data, a dialog box might be more suitable than a
message box. For more information, see Dialog boxes overview.
C#
The MessageBox.Show method overloads provide ways to configure the message box. These
options include:
Display an alert.
C#
The previous code displays a message box like the following image:
It's a good idea to use the options provided by the message box class. Using the same
alert as before, set more options to make it more visually appealing:
C#
The previous code displays a message box like the following image:
Display a warning.
C#
MessageBox.Show("If you close the next window without saving, your changes
will be lost.", "Configuration", MessageBoxButton.OK,
MessageBoxImage.Warning);
The previous code displays a message box like the following image:
C#
The previous code displays a message box like the following image:
Handle a message box response
The MessageBox.Show method displays the message box and returns a result. The result
indicates how the user closed the message box:
C#
switch (result)
{
case MessageBoxResult.Cancel:
// User pressed Cancel
break;
case MessageBoxResult.Yes:
// User pressed Yes
break;
case MessageBoxResult.No:
// User pressed No
break;
}
When a user presses the buttons at the bottom of the message box, the corresponding
MessageBoxResult is returned. However, if the user presses the ESC key or presses the Close
button (#2 in the message box illustration), the result of the message box varies based on the
button options:
ノ Expand table
OK OK
OKCancel Cancel
YesNo ESC keyboard shortcut and Close button disabled. User must press Yes or No.
YesNoCancel Cancel
For more information on using message boxes, see MessageBox and the MessageBox
sample .
See also
Overview of WPF windows
Dialog boxes overview
How to display a common dialog box
MessageBox sample
System.Windows.MessageBox
System.Windows.MessageBox.Show
System.Windows.MessageBoxResult
How to open a window or dialog box
Article • 05/07/2025
You can create your own windows and display them in Windows Presentation Foundation
(WPF). In this article, you'll learn how to display modal and modeless windows and dialogs.
Conceptually, a window and a dialog box are the same thing: they're displayed to a user to
provide information or interaction. They're both "window" objects. The design of the window
and the way it's used, is what makes a dialog box. A dialog box is generally small in size and
requires the user to respond to it. For more information, see Overview of WPF windows and
Dialog boxes overview.
If you're interested in opening operating system dialog boxes, see How to open a common
dialog box.
Open as modal
When a modal window is opened, it generally represents a dialog box. WPF restricts interaction
to the modal window, and the code that opened the window pauses until the window closes.
This mechanism provides an easy way for you to prompt the user with data and wait for their
response.
Use the ShowDialog method to open a window. The following code instantiates the window,
and opens it modally. The code opening the window pauses, waiting for the window to be
closed:
C#
window.Owner = this;
window.ShowDialog();
) Important
Once a window is closed, the same object instance can't be used to reopen the window.
For more information about how to handle the user response to a dialog box, see Dialog boxes
overview: Processing the response.
Open as modeless
Opening a window modeless means displaying it as a normal window. The code that opens the
window continues to run as the window becomes visible. You can focus and interact with all
modeless windows displayed by your application, without restriction.
Use the Show method to open a window. The following code instantiates the window, and
opens it modeless. The code opening the window continues to run:
C#
window.Owner = this;
window.Show();
) Important
Once a window is closed, the same object instance can't be used to reopen the window.
See also
Overview of WPF windows
Dialog boxes overview
How to close a window or dialog box
How to open a common dialog box
How to open a message box
System.Windows.Window
System.Windows.Window.DialogResult
System.Windows.Window.Show()
System.Windows.Window.ShowDialog()
How to close a window or dialog box
Article • 05/07/2025
In this article, you'll learn about the different ways to close a window or dialog box. A user can
close a window by using the elements in the non-client area, including the following:
When designing a window, provide more mechanisms to the client area to close a window.
Some of the common design elements on a window that are used to close it include the
following:
An Exit item in the File menu, typically for main application windows.
A Close item in the File menu, typically on a secondary application window.
A Cancel button, typically on a modal dialog box.
A Close button, typically on a modeless dialog box.
) Important
Once a window is closed, the same object instance can't be used to reopen the window.
For more information about the life of a window, see Overview of WPF windows: Window
lifetime.
C#
Once a window has been closed, it can't be reopened with the same object instance. If you try
to show the same window, a InvalidOperationException is thrown. Instead, create a new
instance of the window and open it.
C#
XAML
Hide a window
Instead of closing a window, a window can be hidden with the Hide method. A hidden window
can be reopened, unlike a window that has been closed. If you're going to reuse a window
object instance, hide the window instead of closing it. The following code demonstrates hiding
a window:
C#
U Caution
If a window is shown modally with ShowDialog, the DialogResult property will be set to
null when the window is hidden. You'll need to communicate state back to the calling
When a window is closed, the Closing event is raised. The handler is passed a CancelEventArgs,
which implements the Cancel property. Set that property to true to prevent a window from
closing. The following code demonstrates how to cancel the closure and instead hide the
window:
C#
There may be times where you don't want to hide a window, but actually prevent the user from
closing it. For more information, see Overview of WPF windows: Cancel window closure.
See also
Overview of WPF windows
Dialog boxes overview
How to open a window or dialog box
System.Windows.Window.Close()
System.Windows.Window.Closing
System.Windows.Window.DialogResult
System.Windows.Window.Hide()
System.Windows.Window.Show()
System.Windows.Window.ShowDialog()
How to open a common dialog box
Article • 05/07/2025
This article demonstrates how you can display a common system dialog box in Windows
Presentation Foundation (WPF). Windows implements different kinds of reusable dialog boxes
that are common to all applications, including dialog boxes for selecting files and printing.
Since these dialog boxes are provided by the operating system, they're shared among all the
applications that run on the operating system. These dialog boxes provide a consistent user
experience, and are known as common dialog boxes. As a user uses a common dialog box in
one application, they don't need to learn how to use that dialog box in other applications.
A message box is another common dialog box. For more information, see How to open a
message box.
The common open file dialog box is implemented as the OpenFileDialog class and is located in
the Microsoft.Win32 namespace. The following code shows how to create, configure, and show
the dialog.
C#
// Configure open file dialog box
var dialog = new Microsoft.Win32.OpenFileDialog();
dialog.FileName = "Document"; // Default file name
dialog.DefaultExt = ".txt"; // Default file extension
dialog.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
For more information on the open file dialog box, see Microsoft.Win32.OpenFileDialog.
The common save file dialog box is implemented as the SaveFileDialog class, and is located in
the Microsoft.Win32 namespace. The following code shows how to create, configure, and show
the dialog.
C#
// Configure save file dialog box
var dialog = new Microsoft.Win32.SaveFileDialog();
dialog.FileName = "Document"; // Default file name
dialog.DefaultExt = ".txt"; // Default file extension
dialog.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
For more information on the save file dialog box, see Microsoft.Win32.SaveFileDialog.
) Important
The Open Folder dialog box is available in .NET 8.0 and later.
The Open Folder dialog box is used by the user to select one or more folders, and return them
to the program. For example, if your program displayed information about a folder, such as the
amount of files and the file names in the folder, you can use the Open Folder dialog to let the
user choose the folder.
The common open folder dialog box is implemented as the OpenFolderDialog class, and is
located in the Microsoft.Win32 namespace. The following code shows how to create, configure,
and show the dialog.
C#
dialog.Multiselect = false;
dialog.Title = "Select a folder";
For more information on the open folder dialog box, see Microsoft.Win32.OpenFolderDialog.
The common print dialog box is implemented as the PrintDialog class, and is located in the
System.Windows.Controls namespace. The following code shows how to create, configure, and
show one.
C#
For more information on the print dialog box, see System.Windows.Controls.PrintDialog. For
detailed discussion of printing in WPF, see Printing overview.
See also
How to open a message box
Dialog boxes overview
Overview of WPF windows
Microsoft.Win32.OpenFileDialog
Microsoft.Win32.SaveFileDialog
System.Windows.Controls.PrintDialog
How to get or set the main application
window
Article • 05/07/2025
This article teaches you how to get or set the main application window for Windows
Presentation Foundation (WPF). The first Window that is instantiated within a WPF application
is automatically set by Application as the main application window. The main window is
referenced with the Application.MainWindow property.
Much of the time a project template will set the Application.StartupUri to a XAML file within
your application, such as _Window1.xaml_. This is the first window instantiated and shown by
your application, and it becomes the main window.
Tip
The default behavior for an application is to shutdown when the last window is closed.
This behavior is controlled by the Application.ShutdownMode property. Instead, you can
configure the application to shutdown if the MainWindow is closed. Set
Application.ShutdownMode to OnMainWindowClose to enable this behavior.
XAML
<Application x:Class="MainApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MainApp"
StartupUri="Window1.xaml">
</Application>
<Application x:Class="MainApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MainApp">
<Application.MainWindow>
<local:Window2 Visibility="Visible" />
</Application.MainWindow>
</Application>
U Caution
Also, you can use the Application.Startup event to open a window. For more information, see
Use the Startup event to open a window.
C#
Application.Current.MainWindow.Show();
If your application has never created an instance of a window, the following code is functionally
equivalent to the previous code:
C#
appWindow.Show();
C#
See also
Overview of WPF windows
Use the Startup event to open a window
How to open a window or dialog box
System.Windows.Application
System.Windows.Application.MainWindow
System.Windows.Application.StartupUri
System.Windows.Application.ShutdownMode
How to: Automatically Size a Window to Fit
Its Content
Article • 05/07/2025
This example shows how to set the SizeToContent property to specify how a window resizes to
fit its content.
Example
C#
Example
Every instantiated Window object, whether visible or not, is automatically added to a collection
of window references that is managed by Application, and exposed from Windows.
You can enumerate Windows to get all instantiated windows using the following code:
C#
Windows Presentation Foundation (WPF) supports browser-style navigation that can be used in
two types of applications: standalone applications and XAML browser applications (XBAPs). To
package content for navigation, WPF provides the Page class. You can navigate from one Page
to another declaratively, by using a Hyperlink, or programmatically, by using the
NavigationService. WPF uses the journal to remember pages that have been navigated from
and to navigate back to them.
Page, Hyperlink, NavigationService, and the journal form the core of the navigation support
offered by WPF. This overview explores these features in detail before covering advanced
navigation support that includes navigation to loose Extensible Application Markup Language
(XAML) files, HTML files, and objects.
7 Note
In this topic, the term "browser" refers only to browsers that can host WPF applications,
which currently includes Microsoft Internet Explorer and Firefox. Where specific WPF
features are supported only by a particular browser, the browser version is referred to.
7 Note
This topic doesn't discuss how to build and deploy XBAPs. For more information on
XBAPs, see WPF XAML Browser Applications Overview.
Implementing a Page
Hyperlink Navigation
Fragment Navigation
Navigation Service
Navigation Lifetime
Cookies
Structured Navigation
Implementing a Page
In WPF, you can navigate to several content types that include .NET Framework objects, custom
objects, enumeration values, user controls, XAML files, and HTML files. However, you'll find that
the most common and convenient way to package content is by using Page. Furthermore, Page
implements navigation-specific features to enhance their appearance and simplify
development.
Using Page, you can declaratively implement a navigable page of XAML content by using
markup like the following.
XAML
A Page that is implemented in XAML markup has Page as its root element and requires the
WPF XML namespace declaration. The Page element contains the content that you want to
navigate to and display. You add content by setting the Page.Content property element, as
shown in the following markup.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Page.Content>
<!-- Page Content -->
Hello, Page!
</Page.Content>
</Page>
Page.Content can only contain one child element; in the preceding example, the content is a
single string, "Hello, Page!" In practice, you will usually use a layout control as the child element
(see Layout) to contain and compose your content.
The child elements of a Page element are considered to be the content of a Page and,
consequently, you don't need to use the explicit Page.Content declaration. The following
markup is the declarative equivalent to the preceding sample.
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<!-- Page Content -->
Hello, Page!
</Page>
In this case, Page.Content is automatically set with the child elements of the Page element. For
more information, see WPF Content Model.
A markup-only Page is useful for displaying content. However, a Page can also display controls
that allow users to interact with the page, and it can respond to user interaction by handling
events and calling application logic. An interactive Page is implemented by using a
combination of markup and code-behind, as shown in the following example.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.HomePage">
Hello, from the XBAP HomePage!
</Page>
C#
using System.Windows.Controls;
namespace SDKSample
{
public partial class HomePage : Page
{
public HomePage()
{
InitializeComponent();
}
}
}
To allow a markup file and code-behind file to work together, the following configuration is
required:
In markup, the Page element must include the x:Class attribute. When the application is
built, the existence of x:Class in the markup file causes Microsoft build engine (MSBuild)
to create a partial class that derives from Page and has the name that is specified by the
x:Class attribute. This requires the addition of an XML namespace declaration for the
In code-behind, the class must be a partial class with the same name that is specified by
the x:Class attribute in markup, and it must derive from Page. This allows the code-
behind file to be associated with the partial class that is generated for the markup file
when the application is built (see Building a WPF Application).
In code-behind, the Page class must implement a constructor that calls the
InitializeComponent method. InitializeComponent is implemented by the markup file's
generated partial class to register events and set properties that are defined in markup.
7 Note
When you add a new Page to your project using Visual Studio, the Page is implemented
using both markup and code-behind, and it includes the necessary configuration to create
the association between the markup and code-behind files as described here.
Once you have a Page, you can navigate to it. To specify the first Page that an application
navigates to, you need to configure the start Page.
An application definition is usually implemented using both markup and code-behind, with the
markup file configured as an MSBuild ApplicationDefinition item. The following is an
application definition for an XBAP.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App" />
C#
using System.Windows;
namespace SDKSample
{
public partial class App : Application { }
}
An XBAP can use its application definition to specify a start Page, which is the Page that is
automatically loaded when the XBAP is launched. You do this by setting the StartupUri property
with the uniform resource identifier (URI) for the desired Page.
7 Note
In most cases, the Page is either compiled into or deployed with an application. In these
cases, the URI that identifies a Page is a pack URI, which is a URI that conforms to the pack
scheme. Pack URIs are discussed further in Pack URIs in WPF. You can also navigate to
content using the http scheme, which is discussed below.
You can set StartupUri declaratively in markup, as shown in the following example.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="PageWithHyperlink.xaml" />
In this example, the StartupUri attribute is set with a relative pack URI that identifies
HomePage.xaml. When the XBAP is launched, HomePage.xaml is automatically navigated to
and displayed. This is demonstrated by the following figure, which shows an XBAP that was
launched from a Web server.
7 Note
For more information regarding the development and deployment of XBAPs, see WPF
XAML Browser Applications Overview and Deploying a WPF Application.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.HomePage"
WindowTitle="Page Title"
WindowWidth="500"
WindowHeight="200">
Hello, from the XBAP HomePage!
</Page>
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page With Hyperlink"
WindowWidth="250"
WindowHeight="250">
XAML
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
Navigate to Another Page
</Hyperlink>
XAML
</Page>
The pack URI of the Page to navigate to, as specified by the NavigateUri attribute.
Content that a user can click to initiate the navigation, such as text and images (for the
content that the Hyperlink element can contain, see Hyperlink).
The following figure shows an XBAP with a Page that has a Hyperlink.
As you would expect, clicking the Hyperlink causes the XBAP to navigate to the Page that is
identified by the NavigateUri attribute. Additionally, the XBAP adds an entry for the previous
Page to the Recent Pages list in Internet Explorer. This is shown in the following figure.
As well as supporting navigation from one Page to another, Hyperlink also supports fragment
navigation.
Fragment Navigation
Fragment navigation is the navigation to a content fragment in either the current Page or
another Page. In WPF, a content fragment is the content that is contained by a named element.
A named element is an element that has its Name attribute set. The following markup shows a
named TextBlock element that contains a content fragment.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page With Fragments" >
XAML
XAML
</Page>
For a Hyperlink to navigate to a content fragment, the NavigateUri attribute must include the
following:
The URI of the Page with the content fragment to navigate to.
A "#" character.
The name of the element on the Page that contains the content fragment.
PageURI # ElementName
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page That Navigates To Fragment" >
XAML
<Hyperlink NavigateUri="PageWithFragments.xaml#Fragment1">
Navigate To pack Fragment
</Hyperlink>
XAML
</Page>
7 Note
This section describes the default fragment navigation implementation in WPF. WPF also
allows you to implement your own fragment navigation scheme which, in part, requires
handling the NavigationService.FragmentNavigation event.
) Important
You can navigate to fragments in loose XAML pages (markup-only XAML files with Page as
the root element) only if the pages can be browsed via HTTP.
Navigation Service
While Hyperlink allows a user to initiate navigation to a particular Page, the work of locating
and downloading the page is performed by the NavigationService class. Essentially,
NavigationService provides the ability to process a navigation request on behalf of client code,
such as the Hyperlink. Additionally, NavigationService implements higher-level support for
tracking and influencing a navigation request.
When a Hyperlink is clicked, WPF calls NavigationService.Navigate to locate and download the
Page at the specified pack URI. The downloaded Page is converted to a tree of objects whose
root object is an instance of the downloaded Page. A reference to the root Page object is
stored in the NavigationService.Content property. The pack URI for the content that was
navigated to is stored in the NavigationService.Source property, while the
NavigationService.CurrentSource stores the pack URI for the last page that was navigated to.
7 Note
It is possible for a WPF application to have more than one currently active
NavigationService. For more information, see Navigation Hosts later in this topic.
When you need to set properties on the Page before you navigate to it.
When the Page that needs to be navigated to can only be determined at run time.
In these situations, you need to write code to programmatically initiate navigation by calling
the Navigate method of the NavigationService object. That requires getting a reference to a
NavigationService.
navigated to a particular Page, you pass a reference to the Page as the argument of the
GetNavigationService method. The following code shows how to get the NavigationService for
the current Page.
C#
using System.Windows.Navigation;
C#
As a shortcut for finding the NavigationService for a Page, Page implements the
NavigationService property. This is shown in the following example.
C#
using System.Windows.Navigation;
C#
7 Note
A Page can only get a reference to its NavigationService when Page raises the Loaded
event.
XAML
<Page
x:Class="SDKSample.PageWithNonDefaultConstructor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PageWithNonDefaultConstructor">
</Page>
C#
using System.Windows.Controls;
namespace SDKSample
{
public partial class PageWithNonDefaultConstructor : Page
{
public PageWithNonDefaultConstructor(string message)
{
InitializeComponent();
this.Content = message;
}
}
}
The Page that navigates to the Page with the non-parameterless constructor is shown in the
following markup and code.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NSNavigationPage">
<Hyperlink Click="hyperlink_Click">
Navigate to Page with Non-Default Constructor
</Hyperlink>
</Page>
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace SDKSample
{
public partial class NSNavigationPage : Page
{
public NSNavigationPage()
{
InitializeComponent();
}
When the Hyperlink on this Page is clicked, navigation is initiated by instantiating the Page to
navigate to using the non-parameterless constructor and calling the
NavigationService.Navigate method. Navigate accepts a reference to the object that the
NavigationService will navigate to, rather than a pack URI.
If you need to construct a pack URI programmatically (when you can only determine the pack
URI at run time, for example), you can use the NavigationService.Navigate method. This is
shown in the following example.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NSUriNavigationPage">
<Hyperlink Click="hyperlink_Click">Navigate to Page by Pack URI</Hyperlink>
</Page>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace SDKSample
{
public partial class NSUriNavigationPage : Page
{
public NSUriNavigationPage()
{
InitializeComponent();
}
A Page is not downloaded if it has the same pack URI as the pack URI that is stored in the
NavigationService.Source property. To force WPF to download the current page again, you can
call the NavigationService.Refresh method, as shown in the following example.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NSRefreshNavigationPage">
<Hyperlink Click="hyperlink_Click">Refresh this page</Hyperlink>
</Page>
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace SDKSample
{
public partial class NSRefreshNavigationPage : Page
{
C#
Navigation Lifetime
There are many ways to initiate navigation, as you've seen. When navigation is initiated, and
while navigation is in progress, you can track and influence the navigation using the following
events that are implemented by NavigationService:
Navigating. Occurs when a new navigation is requested. Can be used to cancel the
navigation.
Navigated. Occurs when the page has been located and downloaded.
LoadCompleted. Occurs when content that was navigated to is loaded and parsed, and
has begun rendering.
After the source content has been loaded, if the desired fragment is in different
content.
The navigation events are raised in the order that is illustrated by the following figure.
In general, a Page isn't concerned about these events. It is more likely that an application is
concerned with them and, for that reason, these events are also raised by the Application class:
Application.Navigating
Application.NavigationProgress
Application.Navigated
Application.NavigationFailed
Application.NavigationStopped
Application.LoadCompleted
Application.FragmentNavigation
Every time NavigationService raises an event, the Application class raises the corresponding
event. Frame and NavigationWindow offer the same events to detect navigation within their
respective scopes.
In some cases, a Page might be interested in these events. For example, a Page might handle
the NavigationService.Navigating event to determine whether or not to cancel navigation away
from itself. This is shown in the following example.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.CancelNavigationPage">
<Button Click="button_Click">Navigate to Another Page</Button>
</Page>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace SDKSample
{
public partial class CancelNavigationPage : Page
{
public CancelNavigationPage()
{
InitializeComponent();
// Can only access the NavigationService when the page has been loaded
this.Loaded += new RoutedEventHandler(CancelNavigationPage_Loaded);
this.Unloaded += new
RoutedEventHandler(CancelNavigationPage_Unloaded);
}
If you register a handler with a navigation event from a Page, as the preceding example does,
you must also unregister the event handler. If you don't, there may be side effects with respect
to how WPF navigation remembers Page navigation using the journal.
) Important
In Internet Explorer, when a user navigates away from and back to an XBAP, only the
journal entries for pages that were not kept alive are retained in the journal. For discussion
on keeping pages alive, see Page Lifetime and the Journal later in this topic.
By default, the text for each Page that appears in the Recent Pages list of Internet Explorer is
the URI for the Page. In many cases, this is not particularly meaningful to the user. Fortunately,
you can change the text using one the following options:
3. The Page.WindowTitle attribute value and the URI for the current Page.
The order in which the options are listed matches the order of precedence for finding the text.
For example, if JournalEntry.Name is set, the other values are ignored.
The following example uses the Page.Title attribute to change the text that appears for a
journal entry.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.PageWithTitle"
Title="This is the title of the journal entry for this page.">
XAML
</Page>
C#
using System.Windows.Controls;
namespace SDKSample
{
public partial class PageWithTitle : Page
{
C#
}
}
You can declaratively add journal navigation support by using the navigation commands
exposed by NavigationCommands. The following example demonstrates how to use the
BrowseBack navigation command.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NavigationCommandsPage">
XAML
<Hyperlink Command="NavigationCommands.BrowseBack">Back</Hyperlink>
XAML
<Hyperlink Command="NavigationCommands.BrowseForward">Forward</Hyperlink>
XAML
</Page>
You can programmatically navigate the journal by using one of the following members of the
NavigationService class:
GoBack
GoForward
CanGoBack
CanGoForward
The journal can also be manipulated programmatically, as discussed in Retaining Content State
with Navigation History later in this topic.
For this reason, the default behavior of the journal is to store Page metadata in each journal
entry rather than a reference to a Page object. When a journal entry is navigated to, its Page
metadata is used to create a new instance of the specified Page. As a consequence, each Page
that is navigated has the lifetime that is illustrated by the following figure.
Although using the default journaling behavior can save on memory consumption, per-page
rendering performance might be reduced; reinstantiating a Page can be time-intensive,
particularly if it has a lot of content. If you need to retain a Page instance in the journal, you can
draw on two techniques for doing so. First, you can programmatically navigate to a Page object
by calling the NavigationService.Navigate method.
Second, you can specify that WPF retain an instance of a Page in the journal by setting the
KeepAlive property to true (the default is false ). As shown in the following example, you can
set KeepAlive declaratively in markup.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.KeepAlivePage"
KeepAlive="True">
</Page>
The lifetime of a Page that is kept alive is subtly different from one that is not. The first time a
Page that is kept alive is navigated to, it is instantiated just like a Page that is not kept alive.
However, because an instance of the Page is retained in the journal, it is never instantiated
again for as long as it remains in the journal. Consequently, if a Page has initialization logic that
needs to be called every time the Page is navigated to, you should move it from the
constructor into a handler for the Loaded event. As shown in the following figure, the Loaded
and Unloaded events are still raised each time a Page is navigated to and from, respectively.
When a Page is not kept alive, you should not do either of the following:
Register event handlers with events that are not implemented by it.
Doing either of these will create references that force the Page to be retained in memory, even
after it has been removed from the journal.
In general, you should prefer the default Page behavior of not keeping a Page alive. However,
this has state implications that are discussed in the next section.
Fortunately, the journal provides support for remembering data across Page navigations,
including control data. Specifically, the journal entry for each Page acts as a temporary
container for the associated Page state. The following steps outline how this support is used
when a Page is navigated from:
2. The state of the Page is stored with the journal entry for that page, which is added to the
back stack.
When the page Page is navigated back to, using the journal, the following steps take place:
1. The Page (the top journal entry on the back stack) is instantiated.
2. The Page is refreshed with the state that was stored with the journal entry for the Page.
WPF automatically uses this support when the following controls are used on a Page:
CheckBox
ComboBox
Expander
Frame
ListBox
ListBoxItem
MenuItem
ProgressBar
RadioButton
Slider
TabControl
TabItem
TextBox
If a Page uses these controls, data entered into them is remembered across Page navigations,
as demonstrated by the Favorite ColorListBox in the following figure.
When a Page has controls other than those in the preceding list, or when state is stored in
custom objects, you need to write code to cause the journal to remember state across Page
navigations.
If you need to remember small pieces of state across Page navigations, you can use
dependency properties (see DependencyProperty) that are configured with the
FrameworkPropertyMetadata.Journal metadata flag.
If the state that your Page needs to remember across navigations comprises multiple pieces of
data, you may find it less code intensive to encapsulate your state in a single class and
implement the IProvideCustomContentState interface.
If you need to navigate through various states of a single Page, without navigating from the
Page itself, you can use IProvideCustomContentState and NavigationService.AddBackEntry.
Cookies
Another way that WPF applications can store data is with cookies, which are created, updated,
and deleted by using the SetCookie and GetCookie methods. The cookies that you can create
in WPF are the same cookies that other types of Web applications use; cookies are arbitrary
pieces of data that are stored by an application on a client machine either during or across
application sessions. Cookie data typically takes the form of a name/value pair in the following
format.
Name = Value
When the data is passed to SetCookie, along with the Uri of the location for which the cookie
should be set, a cookie is created in-memory, and it is only available for the duration of the
current application session. This type of cookie is referred to as a session cookie.
To store a cookie across application sessions, an expiration date must be added to the cookie,
using the following format.
A cookie with an expiration date is stored in the current Windows installation's Temporary
Internet Files folder until the cookie expires. Such a cookie is known as a persistent cookie
because it persists across application sessions.
You retrieve both session and persistent cookies by calling the GetCookie method, passing the
Uri of the location where the cookie was set with the SetCookie method.
The following are some of the ways that cookies are supported in WPF:
WPF standalone applications and XBAPs can both create and manage cookies.
Cookies that are created by an XBAP can be accessed from the browser.
XBAPs from the same domain can create and share cookies.
XBAPs and HTML pages from the same domain can create and share cookies.
Cookies are dispatched when XBAPs and loose XAML pages make Web requests.
Both top-level XBAPs and XBAPs hosted in IFRAMES can access cookies.
In Internet Explorer, P3P policy that pertains to cookies is honored by WPF, particularly
with respect to first-party and third-party XBAPs.
Structured Navigation
If you need to pass data from one Page to another, you can pass the data as arguments to a
non-parameterless constructor of the Page. Note that if you use this technique, you must keep
the Page alive; if not, the next time you navigate to the Page, WPF reinstantiates the Page by
using the parameterless constructor.
Alternatively, your Page can implement properties that are set with the data that needs to be
passed. Things become tricky, however, when a Page needs to pass data back to the Page that
navigated to it. The problem is that navigation doesn't natively support mechanisms for
guaranteeing that a Page will be returned to after it is navigated from. Essentially, navigation
doesn't support call/return semantics. To solve this problem, WPF provides the
PageFunction<T> class that you can use to ensure that a Page is returned to in a predictable
and structured fashion. For more information, see Structured Navigation Overview.
Wizards: Breaking down a complex task into multiple pages that can be navigated
between. An example is the Windows Components Wizard that handles adding and
removing Windows features.
To incorporate browser-style navigation into your standalone applications, you can use the
NavigationWindow class. NavigationWindow derives from Window and extends it with the
same support for navigation that XBAPs provide. You can use NavigationWindow as either the
main window of your standalone application or as a secondary window such as a dialog box.
To implement a NavigationWindow, as with most top-level classes in WPF (Window, Page, and
so on), you use a combination of markup and code-behind. This is shown in the following
example.
XAML
<NavigationWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MainWindow"
Source="HomePage.xaml"/>
C#
using System.Windows.Navigation;
namespace SDKSample
{
public partial class MainWindow : NavigationWindow
{
public MainWindow()
{
InitializeComponent();
}
}
}
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
The following figure shows the NavigationWindow as the main window of a standalone
application.
From the figure, you can see that the NavigationWindow has a title, even though it wasn't set
in the NavigationWindow implementation code from the preceding example. Instead, the title
is set using the WindowTitle property, which is shown in the following code.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Home Page"
WindowTitle="NavigationWindow">
XAML
</Page>
Setting the WindowWidth and WindowHeight properties also affects the NavigationWindow.
Usually, you implement your own NavigationWindow when you need to customize either its
behavior or its appearance. If you do neither, you can use a shortcut. If you specify the pack
URI of a Page as the StartupUri in a standalone application, Application automatically creates a
NavigationWindow to host the Page. The following markup shows how to enable this.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />
C#
As you can see, NavigationWindow displays Internet Explorer-style Back and Forward buttons
that allow users to navigate the journal. These buttons provide the same user experience, as
shown in the following figure.
If your pages provide their own journal navigation support and UI, you can hide the Back and
Forward buttons displayed by NavigationWindow by setting the value of the
ShowsNavigationUI property to false .
Alternatively, you can use customization support in WPF to replace the UI of the
NavigationWindow itself.
The following example shows how to add a Frame to a Page declaratively by using the Frame
element.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page that Hosts a Frame"
WindowWidth="250"
WindowHeight="250">
XAML
XAML
</Page>
This markup sets the Source attribute of the Frame element with a pack URI for the Page that
the Frame should initially navigate to. The following figure shows an XBAP with a Page that has
a Frame that has navigated between several pages.
You don't only have to use Frame inside the content of a Page. It is also common to host a
Frame inside the content of a Window.
By default, Frame only uses its own journal in the absence of another journal. If a Frame is part
of content that is hosted inside either a NavigationWindow or an XBAP, Frame uses the journal
that belongs to the NavigationWindow or XBAP. Sometimes, though, a Frame might need to
be responsible for its own journal. One reason to do so is to allow journal navigation within the
pages that are hosted by a Frame. This is illustrated by the following figure.
In this case, you can configure the Frame to use its own journal by setting the
JournalOwnership property of the Frame to OwnsJournal. This is shown in the following
markup.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page that Hosts a Frame"
WindowWidth="250"
WindowHeight="250">
XAML
XAML
</Page>
The following figure illustrates the effect of navigating within a Frame that uses its own journal.
Notice that the journal entries are shown by the navigation UI in the Frame, rather than by
Internet Explorer.
7 Note
If a Frame is part of content that is hosted in a Window, Frame uses its own journal and,
consequently, displays its own navigation UI.
If your user experience requires a Frame to provide its own journal without showing the
navigation UI, you can hide the navigation UI by setting the NavigationUIVisibility to Hidden.
This is shown in the following markup.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page that Hosts a Frame"
WindowWidth="250"
WindowHeight="250">
XAML
<Frame
Source="FramePage1.xaml"
JournalOwnership="OwnsJournal"
NavigationUIVisibility="Hidden" />
XAML
</Page>
Navigation Hosts
Frame and NavigationWindow are classes that are known as navigation hosts. A navigation
host is a class that can navigate to and display content. To accomplish this, each navigation
host uses its own NavigationService and journal. The basic construction of a navigation host is
shown in the following figure.
Essentially, this allows NavigationWindow and Frame to provide the same navigation support
that an XBAP provides when hosted in the browser.
Besides using NavigationService and a journal, navigation hosts implement the same members
that NavigationService implements. This is illustrated by the following figure.
This allows you to program navigation support directly against them. You may consider this if
you need to provide a custom navigation UI for a Frame that is hosted in a Window.
Furthermore, both types implement additional, navigation-related members, including
BackStack (NavigationWindow.BackStack, Frame.BackStack) and ForwardStack
As mentioned earlier, more than one journal can exist within an application. The following
figure provides an example of when this can happen.
Navigating to Content Other than XAML Pages
Throughout this topic, Page and pack XBAPs have been used to demonstrate the various
navigation capabilities of WPF. However, a Page that is compiled into an application is not the
only type of content that can be navigated to, and pack XBAPs aren't the only way to identify
content.
As this section demonstrates, you can also navigate to loose XAML files, HTML files, and
objects.
For example, consider the following content that is stored as a loose XAML file, Person.xaml.
XAML
When you double-click the file, the browser opens and navigates to and displays the content.
This is shown in the following figure.
A loose XAML file can be added to the browser's favorites, or be the browser's home page.
7 Note
For more information about publishing and launching loose XAML pages, see Deploying a
WPF Application.
One limitation with respect to loose XAML is that you can only host content that is safe to run
in partial trust. For example, Window cannot be the root element of a loose XAML file. For more
information, see WPF Partial Trust Security.
XAML
Like Frame, navigating to HTML using WebBrowser requires special permissions. For example,
from a partial-trust application, you can navigate only to HTML located at the site of origin. For
more information, see WPF Partial Trust Security.
C#
using System.Windows.Media;
namespace SDKSample
{
public class Person
{
string name;
Color favoriteColor;
public Person() { }
public Person(string name, Color favoriteColor)
{
this.name = name;
this.favoriteColor = favoriteColor;
}
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.HomePage"
WindowTitle="Page that Navigates to an Object">
XAML
XAML
</Page>
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace SDKSample
{
public partial class HomePage : Page
{
public HomePage()
{
InitializeComponent();
}
From this figure, you can see that nothing useful is displayed. In fact, the value that is displayed
is the return value of the ToString method for the Person object; by default, this is the only
value that WPF can use to represent your object. You could override the ToString method to
return more meaningful information, although it will still only be a string value. One technique
you can use that takes advantage of the presentation capabilities of WPF is to use a data
template. You can implement a data template that WPF can associate with an object of a
particular type. The following code shows a data template for the Person object.
XAML
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample"
x:Class="SDKSample.App"
StartupUri="HomePage.xaml">
<Application.Resources>
</Application.Resources>
</Application>
Here, the data template is associated with the Person type by using the x:Type markup
extension in the DataType attribute. The data template then binds TextBlock elements (see
TextBlock) to the properties of the Person class. The following figure shows the updated
appearance of the Person object.
An advantage of this technique is the consistency you gain by being able to reuse the data
template to display your objects consistently anywhere in your application.
Security
WPF navigation support allows XBAPs to be navigated to across the Internet, and it allows
applications to host third-party content. To protect both applications and users from harmful
behavior, WPF provides a variety of security features that are discussed in Security and WPF
Partial Trust Security.
See also
SetCookie
GetCookie
Application Management Overview
Pack URIs in WPF
Structured Navigation Overview
Navigation Topologies Overview
How-to Topics
Deploying a WPF Application
Structured Navigation Overview
Article • 05/07/2025
However, other types of applications have pages that do need to know when they have been
navigated between. For example, consider a human resources application that has one page to
list all the employees in an organization—the "List Employees" page. This page could also allow
users to add a new employee by clicking a hyperlink. When clicked, the page navigates to an
"Add an Employee" page to gather the new employee's details and return them to the "List
Employees" page to create the new employee and update the list. This style of navigation is
similar to calling a method to perform some processing and return a value, which is known as
structured programming. As such, this style of navigation is known as structured navigation.
The Page class doesn't implement support for structured navigation. Instead, the
PageFunction<T> class derives from Page and extends it with the basic constructs required for
structured navigation. This topic shows how to establish structured navigation using
PageFunction<T>.
Structured Navigation
When one page calls another page in a structured navigation, some or all of the following
behaviors are required:
The calling page navigates to the called page, optionally passing parameters required by
the called page.
The called page, when a user has completed using the calling page, returns specifically to
the calling page, optionally:
Returning state information that describes how the calling page was completed (for
example, whether a user pressed an OK button or a Cancel button).
Returning that data that was collected from the user (for example, new employee
details).
When the calling page returns to the called page, the called page is removed from
navigation history to isolate one instance of a called page from another.
You can implement these behaviors by using a PageFunction<T> as the called page.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="StructuredNavigationSample.CallingPage"
WindowTitle="Calling Page"
WindowWidth="250" WindowHeight="150">
XAML
</Page>
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
public CallingPage()
{
InitializeComponent();
C#
C#
}
}
XAML
<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="StructuredNavigationSample.CalledPageFunction"
x:TypeArguments="sys:String"
Title="Page Function"
WindowWidth="250" WindowHeight="150">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</PageFunction>
C#
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
public CalledPageFunction()
{
InitializeComponent();
}
C#
}
}
The declaration of a PageFunction<T> is similar to the declaration of a Page with the addition
of the type arguments. As you can see from the code example, the type arguments are
specified in both XAML markup, using the x:TypeArguments attribute, and code-behind, using
standard generic type argument syntax.
You don't have to use only .NET Framework classes as type arguments. A PageFunction<T>
could be called to gather domain-specific data that is abstracted as a custom type. The
following code shows how to use a custom type as a type argument for a PageFunction<T>.
C#
namespace SDKSample
{
public class CustomType
{
C#
}
}
XAML
<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample"
x:Class="SDKSample.CustomTypePageFunction"
x:TypeArguments="local:CustomType">
XAML
</PageFunction>
C#
using System.Windows.Navigation;
namespace SDKSample
{
public partial class CustomTypePageFunction : PageFunction<CustomType>
{
C#
}
}
The type arguments for the PageFunction<T> provide the foundation for the communication
between a calling page and the called page, which are discussed in the following sections.
As you'll see, the type that is identified with the declaration of a PageFunction<T> plays an
important role in returning data from a PageFunction<T> to the calling page.
The following code shows the called page with a non-parameterless constructor to accept
parameters from the calling page.
C#
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
C#
C#
C#
}
}
The following code shows the calling page handling the Click event of the Hyperlink to
instantiate the called page and pass it an initial string value.
XAML
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
public CallingPage()
{
InitializeComponent();
this.pageFunctionHyperlink.Click += new
RoutedEventHandler(pageFunctionHyperlink_Click);
}
void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
{
C#
C#
}
}
You are not required to pass parameters to the called page. Instead, you could do the
following:
But, as you'll see shortly, you'll still need use code to instantiate and navigate to the called
page to collect the data returned by the called page. For this reason, the PageFunction<T>
needs to be kept alive; otherwise, the next time you navigate to the PageFunction<T>, WPF
instantiates the PageFunction<T> using the parameterless constructor.
Before the called page can return, however, it needs to return data that can be retrieved by the
calling page.
1. Whether the user canceled the called page (by pressing either the OK button or the
Cancel button in this example). This allows the calling page to determine whether to
process the data that the calling page gathered from the user.
C#
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
C#
In this example, if a user presses the Cancel button, a value of null is returned to the calling
page. If the OK button is pressed instead, the string value provided by the user is returned.
OnReturn is a protected virtual method that you call to return your data to the calling page.
Your data needs to be packaged in an instance of the generic ReturnEventArgs<T> type, whose
type argument specifies the type of value that Result returns. In this way, when you declare a
PageFunction<T> with a particular type argument, you are stating that a PageFunction<T> will
return an instance of the type that is specified by the type argument. In this example, the type
argument and, consequently, the return value is of type String.
When OnReturn is called, the calling page needs some way of receiving the return value of the
PageFunction<T>. For this reason, PageFunction<T> implements the Return event for calling
pages to handle. When OnReturn is called, Return is raised, so the calling page can register
with Return to receive the notification.
C#
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
C#
// Display result
this.pageFunctionResultsTextBlock.Text = (e != null ? "Accepted" :
"Canceled");
However, unless a called page is removed from the journal, a user will be able to navigate back
to a previous instance of the calling page. Whether a PageFunction<T> is retained in the
journal is determined by the RemoveFromJournal property. By default, a page function is
automatically removed when OnReturn is called because RemoveFromJournal is set to true . To
keep a page function in navigation history after OnReturn is called, set RemoveFromJournal to
false .
For example, sometimes multiple pages are required by a calling page to gather enough data
from a user or to perform a task. The use of multiple pages is referred to as a "wizard".
In other cases, applications may have complex navigation topologies that depend on
structured navigation to operate effectively. For more information, see Navigation Topologies
Overview.
See also
PageFunction<T>
NavigationService
Navigation Topologies Overview
Navigation Topologies Overview
Article • 05/07/2025
7 Note
Before reading this topic, you should be familiar with the concept of structured navigation
in WPF using page functions. For more information on both of these topics, see
Structured Navigation Overview.
Navigation Topologies
Navigation Topologies
In WPF, navigation typically consists of pages (Page) with hyperlinks (Hyperlink) that navigate
to other pages when clicked. Pages that are navigated to are identified by uniform resource
identifiers (URIs) (see Pack URIs in WPF). Consider the following simple example that shows
pages, hyperlinks, and uniform resource identifiers (URIs):
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page1">
<Hyperlink NavigateUri="Page2.xaml">Navigate to Page2</Hyperlink>
</Page>
XAML
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page2">
<Hyperlink NavigateUri="Page1.xaml">Navigate to Page1</Hyperlink>
</Page>
These pages are arranged in a navigation topology whose structure is determined by how you
can navigate between the pages. This particular navigation topology is suitable in simple
scenarios, although navigation can require more complex topologies, some of which can only
be defined when an application is running.
This topic covers three common navigation topologies: fixed linear, fixed hierarchical, and
dynamically generated. Each navigation topology is demonstrated with a sample that has a UI
like the one that is shown in the following figure:
Fixed Topology: defined at compile time and does not change at run time. Fixed
topologies are useful for navigation through a fixed sequence of pages in either a linear
or hierarchical order.
Dynamic Topology: defined at run time based on input that is collected from the user,
the application, or the system. Dynamic topologies are useful when pages can be
navigated in different sequences.
Although it is possible to create navigation topologies using pages, the samples use page
functions because they provide additional support that simplifies support for passing and
returning data through the pages of a topology.
Navigation over a Fixed Linear Topology
A fixed linear topology is analogous to the structure of a wizard that has one or more wizard
pages that are navigated in a fixed sequence. The following figure shows the high-level
structure and flow of a wizard with a fixed linear topology:
The typical behaviors for navigating over a fixed linear topology include the following:
Navigating from the calling page to a launcher page that initializes the wizard and
navigates to the first wizard page. A launcher page (a UI-less PageFunction<T>) is not
required, since a calling page can call the first wizard page directly. Using a launcher
page, however, can simplify wizard initialization, particularly if initialization is complex.
Users can navigate between pages by using Back and Forward buttons (or hyperlinks).
Users can cancel the wizard from any wizard page by pressing a Cancel button.
Users can accept the wizard on the last wizard page by pressing a Finish button.
If a wizard is canceled, the wizard returns an appropriate result, and does not return any
data.
If a user accepts a wizard, the wizard returns an appropriate result, and returns the data it
collected.
When the wizard is complete (accepted or canceled), the pages that the wizard comprises
are removed from the journal. This keeps each instance of the wizard isolated, thereby
avoiding potential data or state anomalies.
This structure is known as a fixed hierarchical topology, and the sequence in which the
hierarchy is traversed is often determined at run time by either the application or the user. At
run time, each page in the hierarchy that allows navigation to two or more other pages gathers
the data required to determine which page to navigate to. The following figure illustrates one
of several possible navigation sequences based on the previous figure:
Even though the sequence in which pages in a fixed hierarchical structure are navigated is
determined at run time, the user experience is the same as the user experience for a fixed
linear topology:
Navigating from the calling page to a launcher page that initializes the wizard and
navigates to the first wizard page. A launcher page (a UI-less PageFunction<T>) is not
required, since a calling page can call the first wizard page directly. Using a launcher
page, however, can simplify wizard initialization, particularly if initialization is complex.
Users can navigate between pages by using Back and Forward buttons (or hyperlinks).
Users can change the navigation sequence if they navigate back through the journal.
Users can cancel the wizard from any wizard page by pressing a Cancel button.
Users can accept the wizard on the last wizard page by pressing a Finish button.
If a wizard is canceled, the wizard returns an appropriate result, and does not return any
data.
If a user accepts a wizard, the wizard returns an appropriate result, and returns the data it
collected.
When the wizard is complete (accepted or canceled), the pages that the wizard comprises
are removed from the journal. This keeps each instance of the wizard isolated, thereby
avoiding potential data or state anomalies.
The next figure illustrates a navigation sequence that was chosen by the user at run time:
The navigation sequence is known as a dynamically generated topology. For the user, as with
the other navigation topologies, the user experience is the same as it is for the previous
topologies:
Navigating from the calling page to a launcher page that initializes the wizard and
navigates to the first wizard page. A launcher page (a UI-less PageFunction<T>) is not
required, since a calling page can call the first wizard page directly. Using a launcher
page, however, can simplify wizard initialization, particularly if initialization is complex.
Users can navigate between pages by using Back and Forward buttons (or hyperlinks).
Users can cancel the wizard from any wizard page by pressing a Cancel button.
Users can accept the wizard on the last wizard page by pressing a Finish button.
If a wizard is canceled, the wizard returns an appropriate result, and does not return any
data.
If a user accepts a wizard, the wizard returns an appropriate result, and returns the data it
collected.
When the wizard is complete (accepted or canceled), the pages that the wizard comprises
are removed from the journal. This keeps each instance of the wizard isolated, thereby
avoiding potential data or state anomalies.
See also
Page
PageFunction<T>
NavigationService
Structured Navigation Overview
Navigation How-to Topics
Article • 05/07/2025
The following topics show how to use Windows Presentation Foundation (WPF) navigation.
In This Section
Call a Page Function Get the Return Value of a Page Function Navigate Forward or Back
Through Navigation History Return from a Page Function
Related Sections
Navigation Overview
This example shows how to call a page function from a Extensible Application Markup
Language (XAML) page.
Example
You can navigate to a page function using a uniform resource identifier (URI), just as you can
when you navigate to a page. This is shown in the following example.
C#
If you need to pass data to the page function, you can create an instance of it and pass the
data by setting a property. Or, as the following example shows, you can pass the data using a
non-parameterless constructor.
XAML
<Page x:Class="UsingPageFunctionsSample.CallingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CallingPage"
>
<Hyperlink Name="callPageFunctionHyperlink"
Click="callPageFunctionHyperlink_Click">Call Page Function</Hyperlink>
</Page>
C#
See also
PageFunction<T>
How to: Navigate to a Page
Article • 05/07/2025
This example illustrates several ways in which a page can be navigated to from a
NavigationWindow.
Example
It is possible for a NavigationWindow to navigate to a page using one of the following:
C#
7 Note
Uniform resource identifiers (URIs) can be either relative or absolute. For more
information, see Pack URIs in WPF.
See also
Frame
Page
NavigationService
How to: Refresh a Page
Article • 05/07/2025
This example shows how to call the Refresh method to refresh the current content in a
NavigationWindow.
Example
Refresh refreshes the current content in a NavigationWindow to be reloaded from its source.
C#
This example shows how to call the StopLoading method to stop navigation to content before
it has finished being downloaded.
Example
StopLoading stops the download of the requested content, and causes the NavigationStopped
event to be raised.
C#
Example
Code that is running from content that is hosted in a NavigationWindow, Frame using
NavigationService, or Internet Explorer can navigate back through navigation history, one entry
at a time.
Navigating back one entry requires first checking that there are entries in back navigation
history, by inspecting the CanGoBack property, before navigating back one entry, by calling
the GoBack method. This is illustrated in the following example:
C#
7 Note
If you call GoBack, and there are no entries in back navigation history, an
InvalidOperationException is raised.
How to: Return from a Page Function
Article • 05/07/2025
Example
To return from a page function, you need to call OnReturn and pass an instance of
ReturnEventArgs<T>.
XAML
<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="UsingPageFunctionsSample.GetStringPageFunction"
x:TypeArguments="sys:String"
Title="GetStringPageFunction">
XAML
</PageFunction>
C#
See also
PageFunction<T>
How to: Get the Return Value of a Page
Function
Article • 05/07/2025
This example shows how to get the result that is returned by a page function.
Example
To get the result that is returned from a page function, you need to handle Return of the page
function you are calling.
XAML
<Page x:Class="UsingPageFunctionsSample.CallingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CallingPage"
>
<Hyperlink Name="callPageFunctionHyperlink"
Click="callPageFunctionHyperlink_Click">Call Page Function</Hyperlink>
</Page>
C#
See also
PageFunction<T>
How to: Navigate Forward or Back Through
Navigation History
Article • 05/07/2025
This example illustrates how to navigate forward or back to entries in navigation history.
Example
Code that runs from content in the following hosts can navigate forward or back through
navigation history, one entry at a time.
Internet Explorer
Before you can navigate forward one entry, you must first check that there are entries in
forward navigation history by inspecting the CanGoForward property. To navigate forward one
entry, you call the GoForward method. This is illustrated in the following example:
C#
Before you can navigate back one entry, you must first check that there are entries in back
navigation history by inspecting the CanGoBack property. To navigate back one entry, you call
the GoBack method. This is illustrated in the following example:
C#
7 Note
If you call GoForward, and there are no entries in forward navigation history, or if you call
GoBack, and there are no entries in back navigation history, an
InvalidOperationException is thrown.
How to: Determine If a Page is Browser
Hosted
Article • 05/07/2025
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
Example
A Page can be host agnostic and, consequently, can be loaded into several different types of
hosts, including a Frame, a NavigationWindow, or a browser. This can happen when you have a
library assembly that contains one or more pages, and which is referenced by multiple
standalone and browsable (XAML browser application (XBAP)) host applications.
C#
See also
Frame
Page
How to: Use mailto: to Send Mail From a
Page
Article • 05/07/2025
This example shows how to use Hyperlink in conjunction with a mailto: uniform resource
identifier (URI).
Example
The following code shows how to use a mailto: uniform resource identifier (URI) to open a new
mail window that contains an email address, and email address and a subject, and an email
address, subject, and body.
XAML
See also
Pack URIs in WPF
How to: Set the Title of a Window from a
Page
Article • 05/07/2025
This example shows how to set the title of the window in which a Page is hosted.
Example
A page can change the title of the window that is hosting it by setting the WindowTitle
property, like so:
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page Title"
WindowTitle="Window Title"
>
</Page>
7 Note
Setting the Title property of a page does not change the value of the window title.
Instead, Title specifies the name of a page entry in navigation history.
How to: Set the Width of a Window from a
Page
Article • 05/07/2025
This example illustrates how to set the width of the window from a Page.
Example
A Page can set the width of its host window by setting WindowWidth. This property allows the
Page to not have explicit knowledge of the type of window that hosts it.
7 Note
To set the width of a window using WindowWidth, a Page must be the child of a window.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SetWindowWidthPage"
WindowWidth="500"
>
</Page>
How to: Set the Height of a Window from a
Page
Article • 05/07/2025
This example illustrates how to set the height of the window from a Page.
Example
A Page can set the height of its host window by setting WindowHeight. This property allows
the Page to not have explicit knowledge of the type of window that hosts it.
7 Note
To set the height of a window using WindowHeight, a Page must be the child of a
window.
XAML
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SetWindowHeightPage"
WindowHeight="500"
>
</Page>
WPF Add-Ins Overview
Article • 05/07/2025
The .NET Framework includes an add-in model that developers can use to create applications
that support add-in extensibility. This add-in model allows the creation of add-ins that
integrate with and extend application functionality. In some scenarios, applications also need
to display user interfaces that are provided by add-ins. This topic shows how WPF augments
the .NET Framework add-in model to enable these scenarios, the architecture behind it, its
benefits, and its limitations.
Prerequisites
Familiarity with the .NET Framework add-in model is required. For more information, see Add-
ins and Extensibility.
Add-Ins Overview
In order to avoid the complexities of application recompilation and redeployment to
incorporate new functionality, applications implement extensibility mechanisms that allow
developers (both first-party and third-party) to create other applications that integrate with
them. The most common way to support this type of extensibility is through the use of add-ins
(also known as "add-ons" and "plug-ins"). Examples of real-world applications that expose
extensibility with add-ins include:
For example, the Windows Media Player add-in model allows third-party developers to
implement "plug-ins" that extend Windows Media Player in a variety of ways, including
creating decoders and encoders for media formats that are not supported natively by Windows
Media Player (for example, DVD, MP3), audio effects, and skins. Each add-in model is built to
expose the functionality that is unique to an application, although there are several entities and
behaviors that are common to all add-in models.
The three main entities of typical add-in extensibility solutions are contracts, add-ins, and host
applications. Contracts define how add-ins integrate with host applications in two ways:
In order for add-ins to be used, host applications need to find them and load them at run time.
Consequently, applications that support add-ins have the following additional responsibilities:
Communication: Allowing add-ins and host applications to communicate with each other
across isolation boundaries by calling methods and passing data.
Versioning: Ensuring that host applications and add-ins can still communicate when new
versions of either are created.
Ultimately, developing a robust add-in model is a non-trivial undertaking. For this reason, the
.NET Framework provides an infrastructure for building add-in models.
7 Note
WPF Add-Ins
WPF, in conjunction with the .NET Framework add-in model, allows you to address a wide
variety of scenarios that require host applications to display user interfaces from add-ins. In
particular, these scenarios are addressed by WPF with the following two programming models:
1. The add-in returns a UI. An add-in returns a UI to the host application via a method call,
as defined by the contract. This scenario is used in the following cases:
The UI for services provided by an add-in differs from the UI of the host applications
that can use the add-in.
The add-in primarily performs a service for the host application, and reports status
to the host application with a UI.
2. The add-in is a UI. An add-in is a UI, as defined by the contract. This scenario is used in
the following cases:
The UI for services provided by an add-in is common to all host applications that
can use that add-in, such as a calculator or color picker.
These scenarios require that UI objects can be passed between host application and add-in
application domains. Since the .NET Framework add-in model relies on remoting to
communicate between application domains, the objects that are passed between them must
be remotable.
A remotable object is an instance of a class that does one or more of the following:
7 Note
For more information regarding the creation of remotable .NET Framework objects, see
Making Objects Remotable.
The WPF UI types are not remotable. To solve the problem, WPF extends the .NET Framework
add-in model to enable WPF UI created by add-ins to be displayed from host applications. This
support is provided by WPF by two types: the INativeHandleContract interface and two static
methods implemented by the FrameworkElementAdapters class: ContractToViewAdapter and
ViewToContractAdapter. At a high level, these types and methods are used in the following
manner:
1. WPF requires that user interfaces provided by add-ins are classes that derive directly or
indirectly from FrameworkElement, such as shapes, controls, user controls, layout panels,
and pages.
2. Wherever the contract declares that a UI will be passed between the add-in and the host
application, it must be declared as an INativeHandleContract (not a FrameworkElement);
INativeHandleContract is a remotable representation of the add-in UI that can be passed
across isolation boundaries.
1. The host application, add-in, and pipeline must be created, as described by the .NET
Framework Add-ins and Extensibility documentation.
2. The contract must implement IContract and, to return a UI, the contract must declare a
method with a return value of type INativeHandleContract.
3. The UI that is passed between the add-in and the host application must directly or
indirectly derive from FrameworkElement.
For an example that demonstrates how to implement an add-in that returns a UI, see Create an
Add-In That Returns a UI.
1. The host application, add-in, and pipeline must be created, as described by the .NET
Framework Add-ins and Extensibility documentation.
3. The add-in that is passed to the host application must directly or indirectly derive from
FrameworkElement.
For an example that demonstrates how to implement an add-in that is a UI, see Create an Add-
In That Is a UI.
The XBAP application manifest must be configured specially to download the pipeline
(folders and assemblies) and add-in assembly to the ClickOnce application cache on the
client machine, in the same folder as the XBAP.
The XBAP code to discover and load add-ins must use the ClickOnce application cache for
the XBAP as the pipeline and add-in location.
The XBAP must load the add-in into a special security context if the add-in references
loose files that are located at the site of origin; when hosted by XBAPs, add-ins can only
reference loose files that are located at the host application's site of origin.
Consequently, the first step is to build the pipeline and add-in assembly to the XBAP project's
root by setting the build output of each pipeline assembly and add-in assembly projects. The
following table shows the build output paths for pipeline assembly projects and add-in
assembly project that are in the same solution and root folder as the host XBAP project.
Table 1: Build Output Paths for the Pipeline Assemblies That Are Hosted by an XBAP
ノ Expand table
Contract ..\HostXBAP\Contracts\
Add-In ..\HostXBAP\AddIns\WPFAddIn1
The next step is to specify the pipeline assemblies and add-in assembly as the XBAPs content
files in Visual Studio by doing the following:
1. Including the pipeline and add-in assembly in the project by right-clicking each pipeline
folder in Solution Explorer and choosing Include In Project.
2. Setting the Build Action of each pipeline assembly and add-in assembly to Content from
the Properties window.
The final step is to configure the application manifest to include the pipeline assembly files and
add-in assembly file for download. The files should be located in folders at the root of the
folder in the ClickOnce cache that the XBAP application occupies. The configuration can be
achieved in Visual Studio by doing the following:
1. Right-click the XBAP project, click Properties, click Publish, and then click the Application
Files button.
2. In the Application Files dialog, set the Publish Status of each pipeline and add-in DLL to
Include (Auto), and set the Download Group for each pipeline and add-in DLL to
(Required).
AddInStore.FindAddIns(Type, PipelineStoreLocation)
AddInStore.Rebuild(PipelineStoreLocation)
AddInStore.Update(PipelineStoreLocation)
For simple UI add-in scenarios, this is as much detail as a developer needs. For more complex
scenarios, particularly those that try to utilize additional WPF services such as layout, resources,
and data binding, more detailed knowledge of how WPF extends the .NET Framework add-in
model with UI support is required to understand its benefits and limitations.
Fundamentally, WPF doesn't pass a UI from an add-in to a host application; instead, WPF
passes the Win32 window handle for the UI by using WPF interoperability. As such, when a UI
from an add-in is passed to a host application, the following occurs:
On the add-in side, WPF acquires a window handle for the UI that will be displayed by the
host application. The window handle is encapsulated by an internal WPF class that derives
from HwndSource and implements INativeHandleContract. An instance of this class is
returned by ViewToContractAdapter and is marshaled from the add-in's application
domain to the host application's application domain.
On the host application side, WPF repackages the HwndSource as an internal WPF class
that derives from HwndHost and consumes INativeHandleContract. An instance of this
class is returned by ContractToViewAdapter to the host application.
HwndHost exists to display user interfaces, identified by window handles, from WPF user
interfaces. For more information, see WPF and Win32 Interoperation.
Because the host application gets an HwndHost, the host application cannot convert the
object that is returned by ContractToViewAdapter to the type it is implemented as by the
add-in (for example, a UserControl).
By its nature, HwndHost has certain limitations that affect how host applications can use them.
However, WPF extends HwndHost with several capabilities for add-in scenarios. These benefits
and limitations are described below.
Tabbing between a host application's UI and an add-in's UI. Note that the "add-in is a UI"
programming model requires the add-in-side adapter to override QueryContract to
enable tabbing, whether the add-in is fully trusted or partially trusted.
Honoring accessibility requirements for add-in user interfaces that are displayed from
host application user interfaces.
Preventing illegal access to add-in UI window handles when add-ins run with security
isolation (that is, a partial-trust security sandbox). Calling ViewToContractAdapter ensures
this security:
For the "add-in returns a UI" programming model, the only way to pass the window
handle for an add-in UI across the isolation boundary is to call ViewToContractAdapter.
For the "add-in is a UI" programming model, overriding QueryContract on the add-in-
side adapter and calling ViewToContractAdapter (as shown in the preceding examples)
is required, as is calling the add-in-side adapter's QueryContract implementation from
the host-side adapter.
Add-in user interfaces displayed from a host application do not respect the host
application's clipping behavior.
Content inside add-in user interfaces that is rendered by drawing operations from the
System.Drawing namespace can include alpha blending. However, both an add-in UI and
the host application UI that contains it must be 100% opaque; in other words, the
Opacity property on both must be set to 1.
An add-in UI must appear on top of other WPF elements in the same top-level window.
When focus shifts between controls in an add-in UI, the GotFocus and LostFocus events
are neither received nor raised by the host application.
The portion of a host application that contains an add-in UI appears white when printed.
All dispatchers (see Dispatcher) created by the add-in UI must be shut down manually
before the owner add-in is unloaded if the host application continues execution. The
contract can implement methods that allow the host application to signal the add-in
before the add-in is unloaded, thereby allowing the add-in UI to shut down its
dispatchers.
Performance Optimization
By default, when multiple application domains are used, the various .NET Framework
assemblies required by each application are all loaded into that application's domain. As a
result, the time required for creating new application domains and starting applications in
them might affect performance. However, the .NET Framework provides a way for you to
reduce start times by instructing applications to share assemblies across application domains if
they are already loaded. You do this by using the LoaderOptimizationAttribute attribute, which
must be applied to the entry point method ( Main ). In this case, you must use only code to
implement your application definition (see Application Management Overview).
See also
LoaderOptimizationAttribute
Add-ins and Extensibility
Application Domains
.NET Framework Remoting Overview
Making Objects Remotable
How-to Topics
How-to Topics
Article • 05/07/2025
The following topics show how to create Windows Presentation Foundation (WPF) add-ins.
In This Section
Create an Add-In That Returns a UI Create an Add-In That Is a UI
Related Sections
WPF Add-Ins Overview
How to: Create an Add-In That Returns a UI
Article • 05/07/2025
This example shows how to create an add-in that returns a Windows Presentation Foundation
(WPF) to a host WPF standalone application.
The add-in returns a UI that is a WPF user control. The content of the user control is a single
button that, when clicked, displays a message box. The WPF standalone application hosts the
add-in and displays the user control (returned by the add-in) as the content of the main
application window.
Prerequisites
This example highlights the WPF extensions to the .NET Framework add-in model that enable
this scenario, and assumes the following:
Knowledge of the .NET Framework add-in model, including pipeline, add-in, and host
development. If you are unfamiliar with these concepts, see Add-ins and Extensibility. For
a tutorial that demonstrates the implementation of a pipeline, an add-in, and a host
application, see Walkthrough: Creating an Extensible Application.
Knowledge of the WPF extensions to the .NET Framework add-in model, which can be
found here: WPF Add-Ins Overview.
Example
To create an add-in that returns a WPF UI requires specific code for each pipeline segment, the
add-in, and the host application.
C#
using System.AddIn.Contract;
using System.AddIn.Pipeline;
namespace Contracts
{
/// <summary>
/// Defines the services that an add-in will provide to a host application
/// </summary>
[AddInContract]
public interface IWPFAddInContract : IContract
{
// Return a UI to the host application
INativeHandleContract GetAddInUI();
}
}
C#
using System.AddIn.Pipeline;
using System.Windows;
namespace AddInViews
{
/// <summary>
/// Defines the add-in's view of the contract
/// </summary>
[AddInBase]
public interface IWPFAddInView
{
// The add-in's implementation of this method will return
// a UI type that directly or indirectly derives from
// FrameworkElement.
FrameworkElement GetAddInUI();
}
}
using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Windows;
using AddInViews;
using Contracts;
namespace AddInSideAdapters
{
/// <summary>
/// Adapts the add-in's view of the contract to the add-in contract
/// </summary>
[AddInAdapter]
public class WPFAddIn_ViewToContractAddInSideAdapter : ContractBase,
IWPFAddInContract
{
IWPFAddInView wpfAddInView;
C#
using System.Windows;
namespace HostViews
{
/// <summary>
/// Defines the host's view of the add-in
/// </summary>
public interface IWPFAddInHostView
{
// The view returns as a class that directly or indirectly derives from
// FrameworkElement and can subsequently be displayed by the host
// application by embedding it as content or sub-content of a UI that is
// implemented by the host application.
FrameworkElement GetAddInUI();
}
}
C#
using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Windows;
using Contracts;
using HostViews;
namespace HostSideAdapters
{
/// <summary>
/// Adapts the add-in contract to the host's view of the add-in
/// </summary>
[HostAdapter]
public class WPFAddIn_ContractToViewHostSideAdapter : IWPFAddInHostView
{
IWPFAddInContract wpfAddInContract;
ContractHandle wpfAddInContractHandle;
public WPFAddIn_ContractToViewHostSideAdapter(IWPFAddInContract
wpfAddInContract)
{
// Adapt the contract (IWPFAddInContract) to the host application's
// view of the contract (IWPFAddInHostView)
this.wpfAddInContract = wpfAddInContract;
// Prevent the reference to the contract from being released while the
// host application uses the add-in
this.wpfAddInContractHandle = new ContractHandle(wpfAddInContract);
}
XAML
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WPFAddIn1.AddInUI">
<StackPanel>
<Button Click="clickMeButton_Click" Content="Click Me!" />
</StackPanel>
</UserControl>
C#
using System.Windows;
using System.Windows.Controls;
namespace WPFAddIn1
{
public partial class AddInUI : UserControl
{
public AddInUI()
{
InitializeComponent();
}
C#
using System.AddIn;
using System.Windows;
using AddInViews;
namespace WPFAddIn1
{
/// <summary>
/// Add-In implementation
/// </summary>
[AddIn("WPF Add-In 1")]
public class WPFAddIn : IWPFAddInView
{
public FrameworkElement GetAddInUI()
{
// Return add-in UI
return new AddInUI();
}
}
}
C#
// Get add-in pipeline folder (the folder in which this application was launched
from)
string appPath = Environment.CurrentDirectory;
See also
Add-ins and Extensibility
WPF Add-Ins Overview
How to: Create an Add-In That Is a UI
Article • 05/07/2025
This example shows how to create an add-in that is a Windows Presentation Foundation (WPF)
which is hosted by a WPF standalone application.
The add-in is a UI that is a WPF user control. The content of the user control is a single button
that, when clicked, displays a message box. The WPF standalone application hosts the add-in
UI as the content of the main application window.
Prerequisites
This example highlights the WPF extensions to the .NET Framework add-in model that enable
this scenario, and assumes the following:
Knowledge of the .NET Framework add-in model, including pipeline, add-in, and host
development. If you are unfamiliar with these concepts, see Add-ins and Extensibility. For
a tutorial that demonstrates the implementation of a pipeline, an add-in, and a host
application, see Walkthrough: Creating an Extensible Application.
Knowledge of the WPF extensions to the .NET Framework add-in model. See WPF Add-Ins
Overview.
Example
To create an add-in that is a WPF UI requires specific code for each pipeline segment, the add-
in, and the host application.
C#
using System.AddIn.Contract;
using System.AddIn.Pipeline;
namespace Contracts
{
/// <summary>
/// Defines the services that an add-in will provide to a host application.
/// In this case, the add-in is a UI.
/// </summary>
[AddInContract]
public interface IWPFAddInContract : INativeHandleContract {}
}
C#
using System.AddIn.Pipeline;
using System.Windows.Controls;
namespace AddInViews
{
/// <summary>
/// Defines the add-in's view of the contract.
/// </summary>
[AddInBase]
public class WPFAddInView : UserControl { }
}
Here, the add-in view is derived from UserControl. Consequently, the add-in UI should also
derive from UserControl.
C#
using System;
using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Security.Permissions;
using AddInViews;
using Contracts;
namespace AddInSideAdapters
{
/// <summary>
/// Adapts the add-in's view of the contract to the add-in contract
/// </summary>
[AddInAdapter]
public class WPFAddIn_ViewToContractAddInSideAdapter : ContractBase,
IWPFAddInContract
{
WPFAddInView wpfAddInView;
/// <summary>
/// ContractBase.QueryContract must be overridden to:
/// * Safely return a window handle for an add-in UI to the host
/// application's application.
/// * Enable tabbing between host application UI and add-in UI, in the
/// "add-in is a UI" scenario.
/// </summary>
public override IContract QueryContract(string contractIdentifier)
{
if
(contractIdentifier.Equals(typeof(INativeHandleContract).AssemblyQualifiedName))
{
return
FrameworkElementAdapters.ViewToContractAdapter(this.wpfAddInView);
}
return base.QueryContract(contractIdentifier);
}
/// <summary>
/// GetHandle is called by the WPF add-in model from the host
application's
/// application domain to get the window handle for an add-in UI from the
/// add-in's application domain. GetHandle is called if a window handle
isn't
/// returned by other means, that is, overriding
ContractBase.QueryContract,
/// as shown above.
/// NOTE: This method requires UnmanagedCodePermission to be called
/// (full-trust by default), to prevent illegal window handle
/// access in partially trusted scenarios. If the add-in could
/// run in a partially trusted application domain
/// (eg AddInSecurityLevel.Internet), you can safely return a window
/// handle by overriding ContractBase.QueryContract, as shown above.
/// </summary>
public IntPtr GetHandle()
{
return
FrameworkElementAdapters.ViewToContractAdapter(this.wpfAddInView).GetHandle();
}
}
}
In the add-in model where an add-in returns a UI (see Create an Add-In That Returns a UI), the
add-in adapter converted the FrameworkElement to an INativeHandleContract by calling
ViewToContractAdapter. ViewToContractAdapter must also be called in this model, although
you need to implement a method from which to write the code to call it. You do this by
overriding QueryContract and implementing the code that calls ViewToContractAdapter if the
code that is calling QueryContract is expecting an INativeHandleContract. In this case, the caller
will be the host-side adapter, which is covered in a subsequent subsection.
7 Note
You also need to override QueryContract in this model to enable tabbing between host
application UI and add-in UI. For more information, see "WPF Add-In Limitations" in WPF
Add-Ins Overview.
C#
using System.Windows.Controls;
namespace HostViews
{
/// <summary>
/// Defines the host's view of the add-in
/// </summary>
public class WPFAddInHostView : UserControl { }
}
This work is performed by the host-side adapter, as shown in the following code.
C#
using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Windows;
using Contracts;
using HostViews;
namespace HostSideAdapters
{
/// <summary>
/// Adapts the add-in contract to the host's view of the add-in
/// </summary>
[HostAdapter]
public class WPFAddIn_ContractToViewHostSideAdapter : WPFAddInHostView
{
IWPFAddInContract wpfAddInContract;
ContractHandle wpfAddInContractHandle;
public WPFAddIn_ContractToViewHostSideAdapter(IWPFAddInContract
wpfAddInContract)
{
// Adapt the contract (IWPFAddInContract) to the host application's
// view of the contract (WPFAddInHostView)
this.wpfAddInContract = wpfAddInContract;
// Prevent the reference to the contract from being released while the
// host application uses the add-in
this.wpfAddInContractHandle = new ContractHandle(wpfAddInContract);
As you can see, the host-side adapter acquires the INativeHandleContract by calling the add-
in-side adapter's QueryContract method (this is the point where the INativeHandleContract
crosses the isolation boundary).
C#
using System.AddIn;
using System.Windows;
using AddInViews;
namespace WPFAddIn1
{
/// <summary>
/// Implements the add-in by deriving from WPFAddInView
/// </summary>
[AddIn("WPF Add-In 1")]
public partial class AddInUI : WPFAddInView
{
public AddInUI()
{
InitializeComponent();
}
From this example, you can see one interesting benefit of this model: add-in developers only
need to implement the add-in (since it is the UI as well), rather than both an add-in class and
an add-in UI.
C#
// Get add-in pipeline folder (the folder in which this application was launched
from)
string appPath = Environment.CurrentDirectory;
// Display add-in UI
this.addInUIHostGrid.Children.Add(this.wpfAddInHostView);
The host application uses typical .NET Framework add-in model code to activate the add-in,
which implicitly returns the host view to the host application. The host application
subsequently displays the host view (which is a UserControl) from a Grid.
The code for processing interactions with the add-in UI runs in the add-in's application
domain. These interactions include the following:
Handling the ButtonClick event.
See also
Add-ins and Extensibility
WPF Add-Ins Overview
Hosting WPF Applications
Article • 05/07/2025
WPF XAML Browser Applications (XBAPs) are rich-client applications that can be deployed to a
Web server and started in a browser. The WPF Host (PresentationHost.exe) is registered as the
shell and MIME handler for XBAP and XAML files. Therefore, Internet Explorer knows to start
the WPF Host when an XBAP is launched. Firefox users can install Firefox add-ons that enable
Firefox to host XBAPs as well. An XBAP can be hosted in other browsers or stand-alone
applications by using the native browser hosting APIs provided by WPF.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
In This Section
WPF XAML Browser Applications Overview WPF Host (PresentationHost.exe) Firefox Add-ons to
Support .NET Application Deployment Native WPF Browser Hosting Support APIs
Related Sections
Application Management Overview Windows in WPF Navigation Overview Build and Deploy
WPF XAML Browser Applications Overview
Article • 05/07/2025
XAML browser applications (XBAPs) combines features of both Web applications and rich-client
applications. Like Web applications, XBAPs can be deployed to a Web server and started from
Internet Explorer or Firefox on Windows. Like rich-client applications, XBAPs can take
advantage of the capabilities of WPF. Developing XBAPs is also similar to rich-client
development. This topic provides a simple, high-level introduction to XBAP development and
describes where XBAP development differs from standard rich-client development.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
Deploying an XBAP
When you run the XBAP project, it opens in a browser window instead of a stand-alone
window. When you debug the XBAP from Visual Studio, the application runs with Internet zone
permission and will therefore throw security exceptions if those permissions are exceeded. For
more information, see Security and WPF Partial Trust Security.
7 Note
If you are not developing with Visual Studio or want to learn more about the project files,
see Building a WPF Application.
Deploying an XBAP
When you build an XBAP, the output includes the following three files:
ノ Expand table
File Description
Executable (.exe) This contains the compiled code and has an .exe extension.
Application manifest This contains metadata associated with the application and has a .manifest
(.manifest) extension.
Deployment manifest This file contains the information that ClickOnce uses to deploy the
(.xbap) application and has the .xbap extension.
You deploy XBAPs to a Web server, for example Microsoft Internet Information Services (IIS) 5.0
or later versions. You do not have to install the .NET Framework on the Web server, but you do
have to register the WPF Multipurpose Internet Mail Extensions (MIME) types and file name
extensions. For more information, see Configure IIS 5.0 and IIS 6.0 to Deploy WPF Applications.
To prepare your XBAP for deployment, copy the .exe and the associated manifests to the Web
server. Create an HTML page that contains a hyperlink to open the deployment manifest, which
is the file that has the .xbap extension. When the user clicks the link to the .xbap file, ClickOnce
automatically handles the mechanics of downloading and starting the application. The
following example code shows an HTML page that contains a hyperlink that points to an XBAP.
HTML
<html>
<head></head>
<body>
<a href="XbapEx.xbap">Click this link to launch the application</a>
</body>
</html>
You can also host an XBAP in the frame of a Web page. Create a Web page with one or more
frames. Set the source property of a frame to the deployment manifest file. If you want to use
the built-in mechanism to communicate between the hosting Web page and the XBAP, you
must host the application in a frame. The following example code shows an HTML page with
two frames, the source for the second frame is set to an XBAP.
HTML
<html>
<head>
<title>A page with frames</title>
</head>
<frameset cols="50%,50%">
<frame src="introduction.htm">
<frame src="XbapEx.xbap">
</frameset>
</html>
In these situations, you can remove the cached version by using the Mage command (installed
with Visual Studio or the Windows SDK) at the command prompt. The following command
clears the application cache.
Console
Mage.exe -cc
This command guarantees that the latest version of your XBAP is started. When you debug
your application in Visual Studio, the latest version of your XBAP should be started. In general,
you should update your deployment version number with each build. For more information
about Mage, see Mage.exe (Manifest Generation and Editing Tool).
3. Make sure that the Grant the application access to its site of origin check box is checked
and then click OK.
4. On the Debug tab, select the Start browser with URL option and specify the URL for the
HTML page that contains the XBAP.
5. In Internet Explorer, click the Tools button and then select Internet Options.
7. In the Settings list under Security, check the Allow active content to run in files on My
Computer check box.
8. Click OK.
The changes will take effect after you restart Internet Explorer.
U Caution
Enabling active content in Internet Explorer may put your computer at risk. If you do not
want to change your Internet Explorer security settings, you can launch the HTML page
from a server and attach the Visual Studio debugger to the process.
When you use a WebBrowser control in your application, WPF internally instantiates the native
WebBrowser ActiveX control. When your application is a partial-trust XBAP running in Internet
Explorer, the ActiveX control runs in a dedicated thread of the Internet Explorer process.
Therefore, the following limitations apply:
The WebBrowser control should provide behavior similar to the host browser, including
security restrictions. Some of these security restrictions can be controlled through the
Internet Explorer security settings. For more information, see Security.
Input is on a separate thread from the WPF WebBrowser, so keyboard input cannot be
intercepted and the IME state is not shared.
The timing or order of navigation may be different due to the ActiveX control running on
another thread. For example, navigating to a page is not always cancelled by starting
another navigation request.
A custom ActiveX control may have trouble with communication since the WPF
application is running in a separate thread.
MessageHook does not get raised because HwndHost cannot subclass a window running
in another thread or process.
2. On the Security tab, select the This is a full trust application option.
This setting makes the following changes:
XML
<PermissionSet class="System.Security.PermissionSet"
version="1"
ID="Custom"
SameSite="site"
Unrestricted="true" />
ノ Expand table
Intranet and trusted Prompt for full trust Sign the XBAP with a certificate so that the user sees the
sites source in the prompt.
Internet Fails with "Trust Not Sign the XBAP with a certificate.
Granted"
7 Note
The behavior described in the previous table is for full-trust XBAPs that do not follow the
ClickOnce Trusted Deployment model.
It is recommended that you use the ClickOnce Trusted Deployment model for deploying a full-
trust XBAP. This model allows your XBAP to be granted full trust automatically, regardless of
the security zone, so that the user is not prompted. As part of this model, you must sign your
application with a certificate from a trusted publisher. For more information, see Trusted
Application Deployment Overview and Introduction to Code Signing.
Starting in .NET Framework 3.5 SP1, XBAP cold-start time is mitigated by displaying an
unmanaged progress page early in the deployment cycle. The progress page appears almost
immediately after the application is started, because it is displayed by native hosting code and
rendered in HTML.
In addition, improved concurrency of the ClickOnce download sequence improves start time by
up to ten percent. After ClickOnce downloads and validates manifests, the application
download starts, and the progress bar starts to update.
See also
Configure Visual Studio to Debug a XAML Browser Application to Call a Web Service
Deploying a WPF Application
WPF Host (PresentationHost.exe)
Article • 05/07/2025
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
Launches the registered HTML handler to host the Windows Presentation Foundation
(WPF) content.
Loads the right versions of the required common language runtime (CLR) and Windows
Presentation Foundation (WPF) assemblies.
Ensures the appropriate permission levels for the zone of deployment are in place.
This topic describes the command line parameters that can be used with PresentationHost.exe.
Usage
PresentationHost.exe [parameters] uri|filename
Parameters
ノ Expand table
Parameter Description
-debug When activating an application, does not commit it to or run it from the store.
This only works when a local file is activated.
-embedding Required by OLE. If the -event or -debug parameter are specified, it is not
necessary to specify the -embedding parameter, since that parameter is set
internally.
-event <eventname> Open the event with this name and signal it when PresentationHost.exe is
initialized and ready to host WPF content. PresentationHost.exe will terminate
if there was an error opening the event, such as if it has not already been
created.
-launchApplication <url> Launches a standalone ClickOnce application from the specified URL. Internet
Explorer and WinINet security policy concerning .NET applications are
applied.
Scenarios
Shell Handler
PresentationHost.exe example.xbap
MIME Handler
PresentationHost.exe -embedding example.xbap
c:\folderpath\example.xbap
See also
Security
Firefox Add-ons to Support .NET
Application Deployment
Article • 05/07/2025
The Windows Presentation Foundation (WPF) plug-in for Firefox and the .NET Framework
Assistant for Firefox enable XAML browser applications (XBAPs), loose XAML, and ClickOnce
applications to work with the Mozilla Firefox browser.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
The WPF plug-in for Firefox is installed with the .NET Framework 3.5. Window 7 includes the
.NET Framework 3.5, but does not include the WPF plug-in for Firefox. You cannot install the
WPF plug-in for Firefox on Windows 7.
The .NET Framework 4 does not include the WPF plug-in for Firefox. However, if both the .NET
Framework 3.5 and .NET Framework 4 are installed, the WPF plug-in for Firefox is installed with
the .NET Framework 3.5. Therefore .NET Framework 4 applications will still run because the
WPF Host will load the correct version of the framework. For more information, see WPF Host
(PresentationHost.exe).
Report all installed versions of the .NET Framework or just the latest version.
The .NET Framework Assistant for Firefox is included with the .NET Framework 3.5 SP1. For
information about removing the .NET Framework Assistant for Firefox, see How to remove the
.NET Framework Assistant for Firefox .
See also
Deploying a WPF Application
WPF XAML Browser Applications Overview
Detect Whether the WPF Plug-In for Firefox Is Installed
Frequently asked questions about WPF
browser-hosted applications (XBAP)
FAQ
Windows Presentation Foundation (WPF) was released as a part of .NET Framework 3.0 in 2006.
The XAML Browser Application (XBAP) feature, which allows WPF apps to be hosted and run in
a web browser, was also introduced at the same time as a part of WPF. At the time of WPF and
XBAP's release in 2006, the most popular web browsers available were Internet Explorer 7,
Mozilla Firefox 2, and Safari 2. Google Chrome wasn't yet available, as it was released two years
later in 2008.
XBAP uses the ClickOnce deployment technology in browsers, which is a Microsoft technology
that allows the user to install and run an app by clicking a link in a web page. However, this
technology relied heavily on the support of NPAPI (Netscape Plugin Application Programming
Interface) in browsers. NPAPI has been phased out in recent years due to security and stability
issues. Major browsers like Edge, Chrome, Firefox, and Safari removed support for NPAPI
plugins, which effectively means that XBAP apps can no longer be run in these browsers.
Migration options
Can I convert my XBAP to a WPF application?
Yes. You can migrate your app to a standard WPF application and deploy it through an installer.
You can still publish a WPF app with ClickOnce, but ClickOnce requires a browser with IE Mode
enabled or a plugin that enables ClickOnce.
Blazor is a full stack web app that uses C#. Depending how well organized and
compartmentalized your code is, you might have to rewrite the front-end of your app in
Blazor. Blazor apps can be deployed using WebAssembly, which lets the app run fully
client-side in the browser.
.NET MAUI
If you created your app as an XBAP so that it could run on non-Windows operating
systems, try converting your app to .NET MAUI, which also uses XAML for its UI. .NET
MAUI is different from WPF, although they share many similar concepts. For more
information, see What is .NET MAUI.
OpenSilver
The OpenSilver project was created as an alternative to Silverlight. Silverlight was a subset
of WPF that was discontinued long ago. Your XBAP project might convert well to
OpenSilver. For more information, see the OpenSilver website and the GitHub
repository .
Native WPF Browser Hosting Support APIs
Article • 05/07/2025
Hosting of WPF applications in Web browsers is facilitated by an Active Document server (also
known as a DocObject) registered out of the WPF Host. Internet Explorer can directly activate
and integrate with an Active Document. For hosting of XBAPs and loose XAML documents in
Mozilla browsers, WPF provides an NPAPI plugin, which provides a similar hosting environment
to the WPF Active Document server as Internet Explorer does. However, the easiest practical
way to host XBAPs and XAML documents in other browsers and standalone applications is via
the Internet Explorer Web Browser control. The Web Browser control provides the complex
Active Document server hosting environment, yet it enables its own host to customize and
extend that environment and communicate directly with the current Active Document object.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
The WPF Active Document server implements several common hosting interfaces, including
IOleObject, IOleDocument, IOleInPlaceActiveObject, IPersistMoniker, IOleCommandTarget.
When hosted in the Web Browser control, these interfaces can be queries from the object
returned by the IWebBrowser2::Document property.
IOleCommandTarget
WPF Active Document server's implementation of IOleCommandTarget supports numerous
navigation-related and browser-specific commands of the standard OLE command group (with
a null command group GUID). In addition, it recognizes a custom command group called
CGID_PresentationHost. Currently, there is only one command defined within this group.
C++
In This Section
IEnumRAWINPUTDEVICE IWpfHostSupport
IEnumRAWINPUTDEVICE
Article • 05/07/2025
This interface enumerates the raw input devices, and is only used by PresentationHost.exe.
7 Note
This API is only intended and supported for use on the local client machine
Members
ノ Expand table
Member Description
IEnumRAWINPUTDEVIC:Skip Instructs the enumerator to skip the next celt elements in the
enumeration so that the next call to IEnumRAWINPUTDEVIC:Next will not
return those elements.
IEnumRAWINPUTDEVIC:Clone Creates another raw input device enumerator with the same state as the
current enumerator to iterate over the same list.
See also
About Raw Input
IEnumRAWINPUTDEVIC:Next
Article • 05/07/2025
Enumerates the next celt RAWINPUTDEVICE structures in the enumerator's list, returning
them in rgelt along with the actual number of enumerated elements in pceltFetched .
Syntax
C++
HRESULT Next(
[in] ULONG celt,
[out, size_is(celt), length_is(*pceltFetched)] RAWINPUTDEVICE *rgelt,
[out] ULONG *pceltFetched);
Parameters
celt
rgelt
[out] Array of size celt (or larger) to receive enumerated RAWINPUTDEVICE structures.
pceltFetched
[out] Pointer to the number of elements actually supplied in rgelt . Caller can pass in NULL if
rgelt is one.
Instructs the enumerator to skip the next celt elements in the enumeration so that the next
call to IEnumRAWINPUTDEVIC:Next will not return those elements.
Syntax
C++
Parameters
celt
Syntax
C++
HRESULT Reset();
Creates another raw input device enumerator with the same state as the current enumerator to
iterate over the same list.
Syntax
C++
Parameters
ppenum
[out] Address of output variable that receives the IEnumRAWINPUTDEVICE interface pointer. If
the method is unsuccessful, the value of this output variable is undefined.
Remarks
This method makes it possible to record a point in the enumeration sequence in order to
return to that point at a later time. The caller must release this new enumerator separately from
the first enumerator.
IWpfHostSupport
Article • 05/07/2025
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
Remarks
Win32 applications such as Web browsers can host WPF content, including XAML browser
applications (XBAPs) and loose XAML. To host WPF content, Win32 applications create an
instance of the WebBrowser control. To be hosted, WPF creates an instance of
PresentationHost.exe, which provides the hosted WPF content to the host for display in the
WebBrowser control.
Discover and register with the raw input devices (Human Interface Devices) that the host
application is interested in.
Receive input messages from the registered raw input devices and forward appropriate
messages to the host application.
Query the host application for custom progress and error user interfaces.
7 Note
This API is only intended and supported for use on the local client machine
Members
ノ Expand table
Member Description
GetRawInputDevices Allows PresentationHost.exe to discover the raw input devices (Human Interface
Devices) that the host application is interested in.
Allows PresentationHost.exe to discover the raw input devices (Human Interface Devices) that
the host application is interested in.
Syntax
C++
Parameters
ppEnum
E_NOTIMPL
Remarks
Raw input devices are the set of input devices that includes keyboards, mice, and less
traditional devices like remote controls.
Once the list of raw input devices has been retrieved, PresentationHost.exe registers with the
devices to receive WM_INPUT notification messages.
See also
GetRawInputDeviceList
FilterInputMessage
FilterInputMessage
Article • 05/07/2025
Syntax
C++
Parameters
pMsg
[in] The WM_INPUT message sent to the window that is getting raw input.
S_OK - The filter did not process the message and further processing may occur.
S_FALSE - The filter processed this message and no further processing should occur.
E_NOTIMPL – If this value is returned, FilterInputMessage is not called again. This might be
returned from a host application that is only interested in providing custom progress and error
user interfaces to PresentationHost.exe is not interested in being forwarded raw input
messages from PresentationHost.exe.
Remarks
PresentationHost.exe is the target of various raw input devices, including keyboard, mice, and
remote controls. Sometimes, behavior in the host application is dependent on input that would
otherwise be consumed by PresentationHost.exe. For example, a host application may depend
on receiving certain input messages to determine whether or not to display specific user
interface elements.
To allow the host application to receive the necessary input messages to provide these
behaviors, PresentationHost.exe forwards appropriate raw input messages to the hosted
application by calling FilterInputMessage.
The hosted application receives raw input messages by registering with the set of raw input
devices (Human Interface Devices) returned by GetRawInputDevices.
See also
WM_INPUT message
GetCustomUI
Article • 05/07/2025
Called by PresentationHost.exe to get custom progress and error messages from the host, if
implemented.
Syntax
C++
Parameters
pwzProgressAssemblyName
[out] A pointer to the assembly that contains the host-supplied progress user interface.
pwzProgressClassName
[out] The name of the class that is the host-supplied progress user interface, preferably a XAML
file with Page is its top-level element. This class resides in the assembly that is specified by
pwzProgressAssemblyName .
pwzErrorAssemblyName
[out] A pointer to the assembly that contains the host-supplied error user interface.
pwzErrorClassName
[out] The name of the class that is the host-supplied error user interface, preferably a XAML file
with Page is its top-level element. This class resides in the assembly that is specified by
pwzErrorAssemblyName .
Remarks
A host application may have a specific theme that PresentationHost.exe’s default user
interfaces may not conform to. If this is the case, the host application can implement
GetCustomUI to return progress and error user interfaces to PresentationHost.exe.
PresentationHost.exe will always call GetCustomUI before using its default user interfaces.
See also
IWpfHostSupport
Building and Deploying WPF Applications
Article • 05/07/2025
The build and deployment model provides the capability to build and deploy applications
locally and remotely, including the following:
In This Section
Building a WPF Application Deploying a WPF Application How-to Topics
Reference
MSBuild
Related Sections
Application Management Overview Windows in WPF Navigation Overview WPF XAML Browser
Applications Overview Hosting
Compile a WPF Application
Article • 05/07/2025
Command-line. The application must contain only code (no XAML) and an application
definition file. For more information, see Command-line Building With csc.exe or Building
from the Command Line (Visual Basic).
Microsoft Build Engine (MSBuild). In addition to the code and XAML files, the application
must contain an MSBuild project file. For more information, see "MSBuild".
Visual Studio. Visual Studio is an integrated development environment that compiles WPF
applications with MSBuild and includes a visual designer for creating UI. For more
information, see Write and manage code using Visual Studio and Design XAML in Visual
Studio.
The first location where 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 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 WPF, and since all WPF assemblies exist at the
same location on every machine that has the .NET Framework installed, there's no need to
include all information on all .NET Framework reference assemblies in the manifests.
Markup Compilation—Pass 1
In this step, XAML files are parsed and compiled so that the runtime does not spend time
parsing XML and validating property values. The compiled XAML file is pre-tokenized so that,
at run time, loading it should be much faster than loading a XAML file.
During this step, the following activities take place for every XAML file that is a Page build item:
2. A compiled representation is created for that 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 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 Page for a page) and
implements the System.Windows.Markup.IComponentConnector interface. The
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:
C#
By default, markup compilation runs in the same AppDomain as the MSBuild engine. This
provides significant performance gains. This behavior can be toggled with the
AlwaysCompileMarkupFilesInSeparateDomain property. This has the advantage of unloading all
Markup Compilation—Pass 2
Not all XAML pages are compiled at during pass 1 of markup compilation. 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 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 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 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 XAML
browser applications (XBAPs)) 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 ClickOnce application, a user opens
the application's deployment manifest file.
These manifest files are always created for XBAPs. For installed applications, they are not
created unless the GenerateManifests property is specified in the project file with value true .
XBAPs get two additional permissions over and above those permissions assigned to typical
Internet zone applications: WebBrowserPermission and MediaPermission. The WPF build
system declares those permissions in the application manifest.
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 XAML page either defines a
class or uses other classes.
If a code file changes, recompile all pages with locally defined type references.
If XAML is declared as Page in the project: if the XAML does not have locally defined
type references, recompile that XAML plus all XAML pages with local references; if the
XAML has local references, recompile all XAML pages with local references.
If the project file declares a code file as application definition instead of a 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 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 .
Only those XAML files that have locally defined type references are recompiled.
See also
Deploying a WPF Application
WPF MSBuild Reference
Pack URIs in WPF
WPF Application Resource, Content, and Data Files
Deploy a WPF Application
Article • 05/07/2025
After Windows Presentation Foundation (WPF) applications are built, they need to be
deployed. Windows and the .NET Framework include several deployment technologies. The
deployment technology that is used to deploy a WPF application depends on the application
type. This topic provides a brief overview of each deployment technology, and how they are
used in conjunction with the deployment requirements of each WPF application type.
Deployment Technologies
Windows and the .NET Framework include several deployment technologies, including:
XCopy deployment.
ClickOnce deployment.
XCopy Deployment
XCopy deployment refers to the use of the XCopy command-line program to copy files from
one location to another. XCopy deployment is suitable under the following circumstances:
The application is self-contained. It does not need to update the client to run.
Application files must be moved from one location to another, such as from a build
location (local disk, UNC file share, and so on) to a publish location (Web site, UNC file
share, and so on).
The application does not require shell integration (Start menu shortcut, desktop icon, and
so on).
Although XCopy is suitable for simple deployment scenarios, it is limited when more complex
deployment capabilities are required. In particular, using XCopy often incurs the overhead for
creating, executing, and maintaining scripts for managing deployment in a robust way.
Furthermore, XCopy does not support versioning, uninstallation, or rollback.
Windows Installer
Windows Installer allows applications to be packaged as self-contained executables that can be
easily distributed to clients and run. Furthermore, Windows Installer is installed with Windows
and enables integration with the desktop, the Start menu, and the Programs control panel.
Windows Installer simplifies the installation and uninstallation of applications, but it does not
provide facilities for ensuring that installed applications are kept up-to-date from a versioning
standpoint.
For more information about Windows Installer, see Windows Installer Deployment.
ClickOnce Deployment
ClickOnce enables Web-style application deployment for non-Web applications. Applications
are published to and deployed from Web or file servers. Although ClickOnce does not support
the full range of client features that Windows Installer-installed applications do, it does support
a subset that includes the following:
Online install mode, which always launches an application from the deployment location.
For more information about ClickOnce, see ClickOnce Security and Deployment.
Standalone applications.
For more information about security for WPF applications, see Security.
Markup-only XAML pages can be installed to the local file system by using either XCopy or
Windows Installer. These pages can be viewed using Internet Explorer or Windows Explorer.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
XBAPs are compiled applications that require the following three files to be deployed:
7 Note
For more information about deployment and application manifests, see Building a WPF
Application.
These files are produced when an XBAP is built. For more information, see How to: Create a
New WPF Browser Application Project. Like markup-only XAML pages, XBAPs are typically
published to a Web server and viewed using Internet Explorer.
XBAPs can be deployed to clients using any of the deployment techniques. However, ClickOnce
is recommended since it provides the following capabilities:
By default, ClickOnce publishes application files with the .deploy extension. This can be
problematic, but can be disabled. For more information, see Server and Client Configuration
Issues in ClickOnce Deployments.
For more information about deploying XAML browser applications (XBAPs), see WPF XAML
Browser Applications Overview.
To detect whether the .NET Framework is installed, Internet Explorer includes a bootstrapper
application that is registered as the fallback Multipurpose Internet Mail Extensions (MIME)
handler for content files with the following extensions: .xaml, .xps, .xbap, and .application. If you
navigate to these file types and the .NET Framework is not installed on the client, the
bootstrapper application requests permission to install it. If permission is not provided, neither
the .NET Framework nor the application is installed.
If permission is granted, Internet Explorer downloads and installs the .NET Framework using the
Microsoft Background Intelligent Transfer Service (BITS). After successful installation of the .NET
Framework, the originally requested file is opened in a new browser window.
For more information, see Deploying the .NET Framework and Applications.
See also
Building a WPF Application
Security
Build and deploy how-to topics
Article • 05/07/2025
The following topics show how to create project files for the various WPF application types.
In this section
Configure IIS 5.0 and IIS 6.0 to Deploy WPF Applications
Configure Visual Studio to Debug a XAML Browser Application to Call a Web Service
Detect Whether the .NET Framework 3.0 Is Installed
Detect Whether the .NET Framework 3.5 Is Installed
Detect Whether the WPF Plug-In for Firefox Is Installed
Related sections
Building a WPF Application
Deploying a WPF Application
Walkthrough: My first WPF desktop application
How to: Create a New WPF Browser Application Project
Determine the Installed Version of WPF (.NET Framework 3.5)
How to: Configure IIS 5.0 and IIS 6.0 to
Deploy WPF Applications
Article • 05/07/2025
You can deploy a Windows Presentation Foundation (WPF) application from most Web servers,
as long as they are configured with the appropriate Multipurpose Internet Mail Extensions
(MIME) types. By default, Microsoft Internet Information Services (IIS) 7.0 is configured with
these MIME types, but Microsoft Internet Information Services (IIS) 5.0 and Microsoft Internet
Information Services (IIS) 6.0 are not.
This topic describes how to configure Microsoft Internet Information Services (IIS) 5.0 and
Microsoft Internet Information Services (IIS) 6.0 to deploy WPF applications.
7 Note
You can check the UserAgent string in the registry to determine whether a system has .NET
Framework installed. For details and a script that examines the UserAgent string to
determine whether .NET Framework is installed on a system, see Detect Whether the .NET
Framework 3.0 Is Installed.
1. Click the Start menu, point to Administrative Tools, and click Internet Information
Services (IIS) Manager. You can also launch this application from the command line with
"%SystemRoot%\system32\inetsrv\iis.msc".
2. Expand the IIS tree until you find the Default Web site node.
3. Right-click Default Web site and select Properties from the context menu.
4. Select the HTTP Headers tab and click "Enable Content Expiration".
.manifest application/manifest
.xaml application/xaml+xml
.application application/x-ms-application
.xbap application/x-ms-xbap
.deploy application/octet-stream
.xps application/vnd.ms-xpsdocument
7 Note
You do not need to register MIME types or file extensions on client systems. They are
registered automatically when you install Microsoft .NET Framework.
The following Microsoft Visual Basic Scripting Edition (VBScript) sample automatically adds the
necessary MIME types to IIS. To use the script, copy the code to a .vbs file on your server. Then,
run the script by running the file from the command line or double-clicking the file in Microsoft
Windows Explorer.
VB
' This script adds the necessary Windows Presentation Foundation MIME types
' to an IIS Server.
' To use this script, just double-click or execute it from a command line.
' Running this script multiple times results in multiple entries in the IIS
MimeMap.
End Sub
7 Note
Running this script multiple times creates multiple MIME map entries in the Microsoft
Internet Information Services (IIS) 5.0 or Microsoft Internet Information Services (IIS) 6.0
metabase.
After you have run this script, you may not see additional MIME types from the Microsoft
Internet Information Services (IIS) 5.0 or Microsoft Internet Information Services (IIS) 6.0
Microsoft Management Console (MMC). However, these MIME types have been added to the
Microsoft Internet Information Services (IIS) 5.0 or Microsoft Internet Information Services (IIS)
6.0 metabase. The following script will display all the MIME types in the Microsoft Internet
Information Services (IIS) 5.0 or Microsoft Internet Information Services (IIS) 6.0 metabase.
VB
' This script lists the MIME types for an IIS Server.
' To use this script, just double-click or execute it from a command line
' by calling cscript.exe
Save the script as a .vbs file (for example, DiscoverIISMimeTypes.vbs ) and run it from the
command prompt using the following command:
Console
cscript DiscoverIISMimeTypes.vbs
How to: Configure Visual Studio to Debug
a XAML Browser Application to Call a Web
Service
Article • 05/07/2025
XAML browser applications (XBAPs) run within a partial-trust security sandbox that is restricted
to the Internet zone set of permissions. This permission set restricts Web service calls to only
Web services that are located at the XBAP application's site of origin. When an XBAP is
debugged from Visual Studio 2005, though, it is not considered to have the same site of origin
as the Web service it references. This causes security exceptions to be raised when the XBAP
attempts to call the Web service. However, a Visual Studio 2005 XAML Browser Application
(WPF) project can be configured to simulate having the same site of origin as the Web service
it calls while debugging. This allows the XBAP to safely call the Web service without causing
security exceptions.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
1. With a project selected in Solution Explorer, on the Project menu, click Properties.
3. In the Start Action section, select Start external program and enter the following:
C:\WINDOWS\System32\PresentationHost.exe
4. In the Start Options section, enter the following into the Command line arguments text
box:
-debug filename
The filename value for the -debug parameter is the .xbap filename; for example:
-debug c:\example.xbap
7 Note
This is the default configuration for solutions that are created with the Visual Studio 2005
XAML Browser Application (WPF) project template.
1. With a project selected in Solution Explorer, on the Project menu, click Properties.
3. In the Start Options section, add the following command-line parameter to the
Command line arguments text box:
-debugSecurityZoneURL URL
The URL value for the -debugSecurityZoneURL parameter is the URL for the location that
you want to simulate as being the site of origin of your application.
As an example, consider a XAML browser application (XBAP) that uses a Web service with the
following URL:
http://services.msdn.microsoft.com/ContentServices/ContentService.asmx
http://services.msdn.microsoft.com
-debugSecurityZoneURL http://services.msdn.microsoft.com
See also
WPF Host (PresentationHost.exe)
How to: Detect Whether the .NET
Framework 3.0 Is Installed
Article • 05/07/2025
Before administrators can deploy Microsoft .NET Framework applications on a system, they
must first confirm that the .NET Framework runtime is present. This topic provides a script
written in HTML/JavaScript that administrators can use to determine whether the .NET
Framework is present on a system.
7 Note
For more detailed information on installing, deploying, and detecting the Microsoft .NET
Framework, see the discussion in Deploying Microsoft .NET Framework Version 3.0.
HTML
<HTML>
<HEAD>
<TITLE>Test for the .NET Framework 3.0</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8" />
<SCRIPT LANGUAGE="JavaScript">
<!--
var dotNETRuntimeVersion = "3.0.04425.00";
function window::onload()
{
if (HasRuntimeVersion(dotNETRuntimeVersion))
{
result.innerText =
"This machine has the correct version of the .NET Framework 3.0: "
+ dotNETRuntimeVersion
}
else
{
result.innerText =
"This machine does not have the correct version of the .NET Framework
3.0."
}
result.innerText += "\n\nThis machine's userAgent string is: " +
navigator.userAgent + ".";
}
//
// Retrieve the version from the user agent string and
// compare with the specified version.
//
function HasRuntimeVersion(versionToCheck)
{
var userAgentString =
navigator.userAgent.match(/.NET CLR [0-9.]+/g);
if (userAgentString != null)
{
var i;
return false;
}
//
// Extract the numeric part of the version string.
//
function GetVersion(versionString)
{
var numericString =
versionString.match(/([0-9]+)\.([0-9]+)\.([0-9]+)/i);
return numericString.slice(1);
}
//
// Compare the 2 version strings by converting them to numeric format.
//
function CompareVersions(version1, version2)
{
for (i = 0; i < version1.length; ++i)
{
var number1 = new Number(version1[i]);
var number2 = new Number(version2[i]);
-->
</SCRIPT>
</HEAD>
<BODY>
<div id="result" />
</BODY>
</HTML>
If the search for the ".NET CLR " version is successful, the following type of status message
appears:
This machine has the correct version of the .NET Framework 3.0: 3.0.04425.00
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;
.NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04425.00).
This machine does not have correct version of the .NET Framework 3.0.
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1;
.NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727).
How to: Detect Whether the .NET
Framework 3.5 Is Installed
Article • 05/07/2025
7 Note
For more detailed information on installing, deploying, and detecting the .NET Framework,
see Install the .NET Framework for developers.
Example
When the .NET Framework 3.5 is installed, the MSI adds ".NET CLR" and the version number to
the UserAgent string. The following example shows a script embedded in a simple HTML page.
The script searches the UserAgent string to determine whether the .NET Framework 3.5 is
installed, and displays a status message on the results of the search.
7 Note
This script is designed for Internet Explorer. Other browsers may not include .NET CLR
information in the UserAgent string.
HTML
<HTML>
<HEAD>
<TITLE>Test for the .NET Framework 3.5</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8" />
<SCRIPT LANGUAGE="JavaScript">
<!--
var dotNETRuntimeVersion = "3.5.0.0";
function window::onload()
{
if (HasRuntimeVersion(dotNETRuntimeVersion))
{
result.innerText =
"This machine has the correct version of the .NET Framework 3.5."
}
else
{
result.innerText =
"This machine does not have the correct version of the .NET Framework
3.5." +
" The required version is v" + dotNETRuntimeVersion + ".";
}
result.innerText += "\n\nThis machine's userAgent string is: " +
navigator.userAgent + ".";
}
//
// Retrieve the version from the user agent string and
// compare with the specified version.
//
function HasRuntimeVersion(versionToCheck)
{
var userAgentString =
navigator.userAgent.match(/.NET CLR [0-9.]+/g);
if (userAgentString != null)
{
var i;
return false;
}
//
// Extract the numeric part of the version string.
//
function GetVersion(versionString)
{
var numericString =
versionString.match(/([0-9]+)\.([0-9]+)\.([0-9]+)/i);
return numericString.slice(1);
}
//
// Compare the 2 version strings by converting them to numeric format.
//
function CompareVersions(version1, version2)
{
for (i = 0; i < version1.length; ++i)
{
var number1 = new Number(version1[i]);
var number2 = new Number(version2[i]);
if (number1 < number2)
return -1;
return 0;
}
-->
</SCRIPT>
</HEAD>
<BODY>
<div id="result" />
</BODY>
</HTML>
If the search for the ".NET CLR " version is successful, the following type of status message
appears:
This machine has the correct version of the .NET Framework 3.5.
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0;
SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.0.590; .NET CLR
3.5.20726; MS-RTC LM 8).
This machine does not have the correct version of the .NET Framework 3.5. The required
version is v3.5.0.0.
This machine's userAgent string is: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0;
SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.0.590; MS-RTC LM 8).
See also
Detect Whether the .NET Framework 3.0 Is Installed
How to: Detect Whether the WPF Plug-In
for Firefox Is Installed
Article • 05/07/2025
The Windows Presentation Foundation (WPF) plug-in for Firefox enables XAML browser
applications (XBAPs) and loose XAML files to run in the Mozilla Firefox browser. This topic
provides a script written in HTML and JavaScript that administrators can use to determine
whether the WPF plug-in for Firefox is installed.
2 Warning
XBAPs require legacy browsers to operate, such as Internet Explorer and old versions of
Firefox. These older browsers are usually unsupported on Windows 10 and Windows 11.
Modern browsers no longer support the technology required for XBAP apps due to
security risks. Plugins that enable XBAPs are no longer supported. For more information,
see Frequently asked questions about WPF browser-hosted applications (XBAP).
7 Note
For more information about installing, deploying, and detecting the .NET Framework, see
Install the .NET Framework for developers.
Example
When the .NET Framework 3.5 is installed, the client computer is configured with a WPF plug-in
for Firefox. The following example script checks for the WPF plug-in for Firefox and then
displays an appropriate status message.
HTML
<HTML>
<HEAD>
<TITLE>Test for the WPF plug-in for Firefox</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8" />
<SCRIPT type="text/javascript">
<!--
function OnLoad()
{
</HTML>
If the check for the WPF plug-in for Firefox is successful, the following status message is
displayed:
The WPF plug-in for Firefox is not installed. Please install or reinstall the .NET
Framework 3.5.
See also
Detect Whether the .NET Framework 3.0 Is Installed
Detect Whether the .NET Framework 3.5 Is Installed
WPF XAML Browser Applications Overview