Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add what's new in WPF #1922

Merged
merged 10 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dotnet-desktop-guide/net/wpf/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ items:
items:
- name: Overview
href: whats-new/index.md
- name: What's new in .NET 9
href: whats-new/net90.md
- name: What's new in .NET 8
href: whats-new/net80.md
- name: What's new in .NET 7
Expand Down
16 changes: 13 additions & 3 deletions dotnet-desktop-guide/net/wpf/whats-new/index.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
---
title: What's new in Windows Presentation Foundation
description: Learn about what's new in Windows Presentation Foundation (WPF). This article covers changes to WPF since .NET 7 was released.
ms.date: 10/24/2024
ms.date: 11/07/2024
ms.topic: conceptual
---

# What's new in Windows Presentation Foundation

Each .NET release introduces a new version of Windows Presentation Foundation (WPF). This article teaches you what's new in each release.

## .NET 9

More support for building modern apps with WPF with several theming enhancements:

- [Overview of WPF on .NET 9](net90.md)
- [Fluent theme](net90.md#fluent-theme)
- [ThemeMode](net90.md#thememode)
- [Support for Windows accent color](net90.md#support-for-windows-accent-color)
- [Hyphen-based ligature support](net90.md#hyphen-based-ligature-support)

## .NET 8

WPF added hardware acceleration for remote desktop apps, and a new control for browsing and selecting folders in .NET 8.

- [Overview of WPF on .NET 8](net80.md).
- [Overview of WPF on .NET 8](net80.md)
- [Hardware acceleration on RDP applications](net80.md#hardware-acceleration)
- [OpenFolderDialog](net80.md#openfolderdialog)

## .NET 7

WPF added some key performance improvements in .NET 7.

- [Overview of WPF on .NET 7](net70.md).
- [Overview of WPF on .NET 7](net70.md)
- [Performance improvements](net70.md#performance-improvements)
- [Accessibility improvements and fixes](net70.md#accessibility-improvements-and-fixes)
- [Bug fixes](net70.md#bug-fixes)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions dotnet-desktop-guide/net/wpf/whats-new/net90.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
title: What's new in WPF for .NET 9
description: Learn about what's new in Windows Presentation Foundation (WPF) for .NET 9. New versions of WPF are released yearly with .NET.
ms.topic: whats-new
ms.date: 11/08/2024

#customer intent: As a developer, I want to know what's changed so that I can remain up-to-date.

---

# What's new in WPF for .NET 9

This article describes what's new in Windows Presentation Foundation (WPF) for .NET 9. The main area of focus for WPF this year was improving the visual capabilities of WPF and providing a new theme based on the Fluent design principles for Windows 11.

You can preview the new theme by downloading the **WPF Gallery** app from the [Microsoft Store](https://www.microsoft.com/store/productId/9NDLX60WX4KQ).

## Fluent theme

A new theme is included with WPF that delivers a fresh, modern Windows 11 aesthetic for WPF apps. It includes integrated light and dark modes, and a system accent color support.

- Fluent theme in light mode:

:::image type="content" source="./media/net90/wpf-light.png" lightbox="./media/net90/wpf-light.png" alt-text="A screenshot of the WPF Gallery app, demonstrating the fluent theme in light mode.":::

- Fluent theme in dark mode:

:::image type="content" source="./media/net90/wpf-dark.png" lightbox="./media/net90/wpf-dark.png" alt-text="A screenshot of the WPF Gallery app, demonstrating the fluent theme in dark mode":::

### Apply the theme

You can apply the Fluent theme in two ways, setting the `ThemeMode` property or referencing the Fluent theme resource dictionary. For more information about the theme mode setting, see [ThemeMode](#thememode).

The Fluent theme resource dictionary is available at the following pack URI: `/PresentationFramework.Fluent;component/Themes/Fluent.xaml`. To apply the resource at the application-level, load the resource into your app's resources:

```xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
```

The resource dictionary can also be applied to a `Window` to theme just the window itself.

## ThemeMode

A new styling API has been added to WPF, which is exposed through the `ThemeMode` property. By using this property, you can apply the Fluent style without having to reference a styling resource dictionary directly.

Available values are:

- `Light`&mdash;Applies the light Fluent theme.
- `Dark`&mdash;Applies the dark Fluent theme.
- `System`&mdash;Applies either the light or dark Fluent theme, based on the user's current Windows setting.
- `None`&mdash;(default) Uses the Aero2 theme.

To apply a theme mode for the whole application, set the `ThemeMode` property on the `Application` type. To apply it to a single window, set `ThemeMode` on the `Window` type.

For example, style the entire application based on the current light or dark theme set by Windows:

:::code language="csharp" source=".\snippets\net90\csharp\App.xaml" range="1-6" highlight="6":::

Here's an example of forcing the light theme, regardless of the theme set by Windows:

:::code language="csharp" source=".\snippets\net90\csharp\LightWindow.xaml" range="1-6" highlight="6":::

If the `ThemeMode` is set to any value other than `None` at the application-level, `None` can no longer be applied at the window-level.

`ThemeMode` is designed to respect the settings set by a Fluent Dictionary, allowing you to customize the Fluent theme.

### Set in code

Support for changing setting the `ThemeMode` in code is currently an experimental feature. Accessing the `ThemeMode` property in code generates error **WPF0001**, preventing access to the API. Suppress the error to access to the API.

> [!WARNING]
> This API is experimental and subject to change.

First, add the following `PropertyGroup` element to your project file to suppress the error:

:::code language="xml" source=".\snippets\net90\csharp\MyWpfProject.csproj" id="NoWarn":::

> [!TIP]
> You can use the `#pragma warning disable WPF0001` directive to suppress the error where it occurs instead of disabling it for the entire project.

Next, set either the `ThemeMode` property at the application-level or window-level:

:::code language="csharp" source=".\snippets\net90\csharp\MainWindow.xaml.cs" id="ThemeMode":::

## Support for Windows accent color

Windows 10 introduced a user-selectable accent color that's used in providing a personal touch or calling out a specific visual element. WPF now supports the user-selected accent color.

The visual color is available as a `System.Windows.Media.Color`, `System.Windows.Media.SolidColorBrush`, or `System.Windows.ResourceKey`. Along with the color itself, light and dark shades of the accent color are available. These are accessed through `System.Windows.SystemColors`:

| | Color | Color Resource Key | Brush | Brush Resource Key |
|---------|---------------------|------------------------|--------------------------|-----------------------------|
| Accent | `AccentColor` | `AccentColorKey` | `AccentColorBrush` | `AccentColorBrushKey` |
| Light 1 | `AccentColorLight1` | `AccentColorLight1Key` | `AccentColorLight1Brush` | `AccentColorLight1BrushKey` |
| Light 2 | `AccentColorLight2` | `AccentColorLight2Key` | `AccentColorLight2Brush` | `AccentColorLight2BrushKey` |
| Light 3 | `AccentColorLight3` | `AccentColorLight3Key` | `AccentColorLight3Brush` | `AccentColorLight3BrushKey` |
| Dark 1 | `AccentColorDark1` | `AccentColorDark1Key` | `AccentColorDark1Brush` | `AccentColorDark1BrushKey` |
| Dark 2 | `AccentColorDark2` | `AccentColorDark2Key` | `AccentColorDark2Brush` | `AccentColorDark2BrushKey` |
| Dark 3 | `AccentColorDark3` | `AccentColorDark3Key` | `AccentColorDark3Brush` | `AccentColorDark3BrushKey` |

> [!IMPORTANT]
> Accent colors are available with or without the Fluent theme.

When creating a UI that uses the accent color, wrap the resource key in a dynamic resource. When a user changes the accent color while the app is opened, the color is updated automatically in the app. For example, here's a `TextBlock` with the foreground color set to the user's chosen accent color:

:::code language="xaml" source=".\snippets\net90\csharp\MainWindow.xaml" id="DynamicAccent":::

## Hyphen-based ligature support

WPF has never supported hyphen-based ligatures in UI controls such as the `TextBlock`. This long-standing community ask was added in .NET 9.

Here's an image of the ligatures not being applied to the glyphs in .NET 8:

:::image type="content" source="./media/net90/ligature-8.png" alt-text="A screenshot of a simple WPF app that has a text block showing how glyphs aren't combined into ligatures with .NET 8.":::

And now, that same text as rendered in .NET 9:

:::image type="content" source="./media/net90/ligature-9.png" alt-text="A screenshot of a simple WPF app that has a text block showing how glyphs are combined into ligatures with .NET 9.":::
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Application x:Class="MyWpfProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWpfProject"
StartupUri="MainWindow.xaml"
ThemeMode="System">
<Application.Resources>

</Application.Resources>
</Application>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Configuration;
using System.Data;
using System.Windows;

namespace MyWpfProject;

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Windows;

[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Window x:Class="MyWpfProject.DarkWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWpfProject"
Title="DarkWindow" Height="450" Width="800"
ThemeMode="Dark">

<local:UserControl1 />

</Window>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace MyWpfProject
{
/// <summary>
/// Interaction logic for DarkWindow.xaml
/// </summary>
public partial class DarkWindow : Window
{
public DarkWindow()
{
InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Window x:Class="MyWpfProject.LightWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWpfProject"
Title="LightWindow" Height="450" Width="800"
ThemeMode="Light">

<local:UserControl1 />

</Window>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace MyWpfProject
{
/// <summary>
/// Interaction logic for LightWindow.xaml
/// </summary>
public partial class LightWindow : Window
{
public LightWindow()
{
InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Window x:Class="MyWpfProject.MainWindow"
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:MyWpfProject"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="2"/>
<Setter Property="Width" Value="300" />
</Style>
</Window.Resources>
<StackPanel HorizontalAlignment="Center">
<Button Content="Dark Window" Click="ShowDark_Click" Background="{x:Static SystemColors.AccentColorDark1Brush}" />
<Button Content="Light Window" Click="ShowLight_Click" Background="{x:Static SystemColors.AccentColorDark2Brush}" />
<Button Content="Theme" Click="ShowTheme_Click" Background="{x:Static SystemColors.AccentColorDark3Brush}" />
<Button Content="Directly set light theme app" Click="SetLightThemeApp_Click" Background="{DynamicResource {x:Static SystemColors.AccentColorBrushKey}}" />
<RadioButton Content="Just some other control" />
<!--<DynamicAccent>-->
<TextBlock Text="First Name:"
Foreground="{DynamicResource {x:Static SystemColors.AccentColorBrushKey}}" />
<!--</DynamicAccent>-->
</StackPanel>
</Window>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MyWpfProject;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private void ShowDark_Click(object sender, RoutedEventArgs e)
{
DarkWindow window = new();
window.Show();
}
private void ShowLight_Click(object sender, RoutedEventArgs e)
{
LightWindow window = new();
window.Show();
}
private void ShowTheme_Click(object sender, RoutedEventArgs e)
{
ThemeWindow window = new();
window.Show();
}
private void SetLightThemeApp_Click(object sender, RoutedEventArgs e)
{
//<ThemeMode>
// Set light mode at the application-level
Application.Current.ThemeMode = ThemeMode.Light;

// Set dark mode on the current window
this.ThemeMode = ThemeMode.Dark;
//</ThemeMode>
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>

<!--<NoWarn>-->
<PropertyGroup>
<NoWarn>WPF0001</NoWarn>
</PropertyGroup>
<!--</NoWarn>-->

</Project>
Loading
Loading