Skip to content

Commit 10adbf7

Browse files
michael-hawkervgromfeldniels9001
authored
StackedNotificationsBehavior port (CommunityToolkit#170)
* Port over content for StackedNotificationBehavior from Labs to Behaviors component * Make notifications cycle vs. be completely random so easier to see new notification in sample * Add more complete documentation and examples on Migrating from prior Toolkit control Adds additional `Show` methods to act as backward compatibile helpers. * Add IconSource to Notification for StackedNotificationsBehavior * Add an initial test for the StackedNotifications Behavior * Make Title and Severity work like Overrides, so parent InfoBar can have constant values for Notifications Added test for override scenario * Add test for Duration of StackedNoticationsBehavior * Added test for cancelling the close of a notification from the InfoBar Closing event Added a Clear method to clear all notifications on the StackedNotificationsBehavior Added more migration notes * Fix warnings about possible null reference assignment * Missed MUXC prefix * Updating icon * Minor sample tweaks * Update Build Script to emit more diagnostics for diagnosing test issues * Fix potential issue with Timer still activating after clean-up of StackedNotificationsBehavior * Add some more automatic analysis and try ignoring a specific test... --------- Co-authored-by: Vincent Gromfeld <[email protected]> Co-authored-by: Niels Laute <[email protected]>
1 parent 4194901 commit 10adbf7

15 files changed

+928
-4
lines changed

.github/workflows/build.yml

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ on:
1818

1919
env:
2020
DOTNET_VERSION: ${{ '7.0.x' }}
21-
ENABLE_DIAGNOSTICS: false
21+
ENABLE_DIAGNOSTICS: true
2222
#COREHOST_TRACE: 1
2323
COREHOST_TRACEFILE: corehosttrace.log
2424
MULTI_TARGET_DIRECTORY: tooling/MultiTarget
@@ -68,6 +68,22 @@ jobs:
6868

6969
# Steps represent a sequence of tasks that will be executed as part of the job
7070
steps:
71+
- name: Configure Pagefile
72+
uses: al-cheb/[email protected]
73+
with:
74+
minimum-size: 32GB
75+
maximum-size: 32GB
76+
disk-root: "C:"
77+
78+
- name: Enable User-Mode Dumps collecting
79+
if: ${{ env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '' }}
80+
shell: powershell
81+
run: |
82+
New-Item '${{ github.workspace }}\CrashDumps' -Type Directory
83+
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' -Name 'DumpFolder' -Type ExpandString -Value '${{ github.workspace }}\CrashDumps'
84+
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' -Name 'DumpCount' -Type DWord -Value '10'
85+
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' -Name 'DumpType' -Type DWord -Value '2'
86+
7187
- name: Install .NET SDK v${{ env.DOTNET_VERSION }}
7288
uses: actions/setup-dotnet@v3
7389
with:
@@ -106,8 +122,13 @@ jobs:
106122
run: powershell -version 5.1 -command "./UseUnoWinUI.ps1 3" -ErrorAction Stop
107123
if: ${{ matrix.platform == 'WinUI3' }}
108124

125+
- name: MSBuild (With diagnostics)
126+
if: ${{ env.ENABLE_DIAGNOSTICS == 'true' }}
127+
run: msbuild.exe CommunityToolkit.AllComponents.sln /restore /nowarn:MSB4011 -p:Configuration=Release -m /bl -v:diag
128+
109129
- name: MSBuild
110-
run: msbuild.exe CommunityToolkit.AllComponents.sln /restore /nowarn:MSB4011 -p:Configuration=Release -m -p:UseDotNetNativeToolchain=false
130+
if: ${{ env.ENABLE_DIAGNOSTICS == 'false' }}
131+
run: msbuild.exe CommunityToolkit.AllComponents.sln /restore /nowarn:MSB4011 -p:Configuration=Release -m
111132

112133
# Build All Packages
113134
- name: pack experiments
@@ -125,7 +146,7 @@ jobs:
125146

126147
# Run tests
127148
- name: Setup VSTest Path
128-
uses: darenm/Setup-VSTest@v1
149+
uses: darenm/Setup-VSTest@v1.2
129150

130151
- name: Install Testspace Module
131152
uses: testspace-com/setup-testspace@v1
@@ -152,6 +173,36 @@ jobs:
152173
name: build-logs
153174
path: ./**/*.*log
154175

176+
- name: Artifact - ILC Repro
177+
uses: actions/upload-artifact@v3
178+
if: ${{ (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
179+
with:
180+
name: ilc-repro
181+
path: ./*.zip
182+
183+
# https://github.com/dorny/paths-filter#custom-processing-of-changed-files
184+
- name: Detect If any Dump Files
185+
uses: dorny/[email protected]
186+
id: filter
187+
with:
188+
list-files: shell
189+
filters: |
190+
dump:
191+
- added: '${{ github.workspace }}/CrashDumps/*.dmp'
192+
193+
- name: Artifact - WER crash dumps
194+
uses: actions/upload-artifact@v3
195+
if: ${{ steps.filter.outputs.dump == 'true' && (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
196+
with:
197+
name: CrashDumps-${{ matrix.platform }}
198+
path: '${{ github.workspace }}/CrashDumps'
199+
200+
- name: Analyze Dump
201+
if: ${{ steps.filter.outputs.dump == 'true' && (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
202+
run: |
203+
dotnet tool install --global dotnet-dump
204+
dotnet-dump analyze ${{ steps.filter.outputs.dump_files }} -c "clrstack" -c "pe -lines" -c "exit"
205+
155206
wasm-linux:
156207
runs-on: ubuntu-latest
157208

Loading

components/Behaviors/samples/Behaviors.Samples.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</ItemGroup>
1616
<ItemGroup>
1717
<Content Include="Assets\ToolkitIcon.png">
18-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
18+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1919
</Content>
2020
</ItemGroup>
2121
</Project>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
title: StackedNotificationsBehavior
3+
author: vgromfeld
4+
description: A behavior to add stacked notifications to a WinUI InfoBar control.
5+
keywords: StackedNotificationsBehavior, Control, Layout, InfoBar, Behavior
6+
dev_langs:
7+
- csharp
8+
category: Xaml
9+
subcategory: Behaviors
10+
discussion-id: 0
11+
issue-id: 0
12+
icon: Assets/StackedNotificationsBehavior.png
13+
---
14+
15+
The `StackedNotificationsBehavior` allows you to provide notifications within your app using an `InfoBar` control. This is a replacement for the prior `InAppNotification` control in the Toolkit.
16+
17+
With the default settings, a notification will be displayed until it is dismissed by the user. Any subsequent notifications will be displayed
18+
in the order of being sent afterwards one-by-one.
19+
20+
## Example
21+
22+
Clicking on the button multiple times will queue up multiple messages to be displayed one after another.
23+
24+
> [!Sample StackedNotificationsBehaviorCustomSample]
25+
26+
## Notification options
27+
28+
By default, the properties provided on the attached `InfoBar` will be used, like `ContentTemplate` or `IsIconVisible`.
29+
30+
However, there are a number of options available on the `Notification` class to override these. When set, these will override any defaults
31+
or modified properties set on the parent `InfoBar` itself. They will be restored to the previously set value on the `InfoBar` after the message has been displayed.
32+
33+
> [!WARNING]
34+
> Properties set on the `InfoBar` will be modified directly by the behavior with notification overrides, this means any bindings will
35+
> be broken by that change when it is overridden or restored by the notification. Therefore, it is best to only provide constants on the
36+
> parent `InfoBar` itself that will be consistent for all messages and set any dynamic options in the `Notification` options.
37+
38+
When a `Duration` is provided, if the user has their pointer over the message, it will not be dismissed. It will instead reset the time before
39+
being dismissed once the pointer has left the active notification.
40+
41+
## Migrating from InAppNotification
42+
43+
If you previously used the `InAppNotification` component from the Windows Community Toolkit, like so:
44+
45+
```xml
46+
<controls:InAppNotification x:Name="ExampleInAppNotification"/>
47+
```
48+
49+
You can simply replace it with an `InfoBar` control and add the attached behavior:
50+
51+
```xml
52+
<muxc:InfoBar>
53+
<interactivity:Interaction.Behaviors>
54+
<behaviors:StackedNotificationsBehavior x:Name="ExampleInAppNotification" />
55+
</interactivity:Interaction.Behaviors>
56+
</muxc:InfoBar>
57+
```
58+
59+
There are some changes to the `Show` method, however a simple text based one has been provided for backwards compatibility,
60+
otherwise it's best to construct your own `Notification` object for greater flexibility or set common properties on the
61+
parent `InfoBar` itself.
62+
63+
> [!NOTE]
64+
> There is no `StackMode` property to control the behavior of the queue. Providing a stable queue of messages one after another
65+
> provides the best user experience as it reduces the risk when interacting with a notification for a new one to suddenly appear
66+
> and replace the one being displayed.
67+
68+
The `ShowDismissButton` property should be mapped to the `InfoBar.IsClosable` property instead. Similar to any adjustments to position
69+
should be handled by the layout of the `InfoBar` control itself within the XAML layout.
70+
71+
The `Closing` and `Closed` events can be mapped to those on the `InfoBar` as well.
72+
73+
### Complete example
74+
75+
This example shows sending simple text based notifications that will appear only for 2 seconds:
76+
77+
> [!Sample StackedNotificationsBehaviorToolkitSample]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
2+
<Page x:Class="BehaviorsExperiment.Samples.StackedNotificationsBehaviorCustomSample"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
10+
mc:Ignorable="d">
11+
12+
<Grid MinHeight="186">
13+
<Button HorizontalAlignment="Left"
14+
VerticalAlignment="Top"
15+
Click="Button_Click"
16+
Content="Send notification" />
17+
18+
<muxc:InfoBar MaxWidth="480"
19+
Margin="24"
20+
HorizontalAlignment="Right"
21+
VerticalAlignment="Bottom">
22+
<interactivity:Interaction.Behaviors>
23+
<behaviors:StackedNotificationsBehavior x:Name="NotificationQueue" />
24+
</interactivity:Interaction.Behaviors>
25+
</muxc:InfoBar>
26+
</Grid>
27+
</Page>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using CommunityToolkit.WinUI.Behaviors;
6+
7+
namespace BehaviorsExperiment.Samples;
8+
9+
[ToolkitSample(id: nameof(StackedNotificationsBehaviorCustomSample), "Stacked Notifications", description: $"A sample for showing how to create and use a {nameof(StackedNotificationsBehavior)} custom behavior.")]
10+
public sealed partial class StackedNotificationsBehaviorCustomSample : Page
11+
{
12+
public StackedNotificationsBehaviorCustomSample()
13+
{
14+
this.InitializeComponent();
15+
}
16+
17+
private void Button_Click(object sender, RoutedEventArgs e)
18+
{
19+
var notification = new Notification
20+
{
21+
Title = $"Notification {DateTimeOffset.Now}",
22+
Message = GetRandomText(),
23+
Severity = MUXC.InfoBarSeverity.Informational,
24+
};
25+
26+
NotificationQueue.Show(notification);
27+
}
28+
29+
private static int _current = 0;
30+
31+
private static string GetRandomText() => (_current++ % 4) switch
32+
{
33+
1 => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin bibendum enim at tincidunt. Praesent egestas ipsum ligula, nec tincidunt lacus semper non.",
34+
2 => "Pellentesque in risus eget leo rhoncus ultricies nec id ante.",
35+
3 => "Sed quis nisi quis nunc condimentum varius id consectetur metus. Duis mauris sapien, commodo eget erat ac, efficitur iaculis magna. Morbi eu velit nec massa pharetra cursus.",
36+
_ => "Fusce non quam egestas leo finibus interdum eu ac massa. Quisque nec justo leo. Aenean scelerisque placerat ultrices. Sed accumsan lorem at arcu commodo tristique.",
37+
};
38+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
2+
<Page x:Class="BehaviorsExperiment.Samples.StackedNotificationsBehaviorToolkitSample"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
10+
mc:Ignorable="d">
11+
12+
<StackPanel MinHeight="136"
13+
Orientation="Vertical"
14+
Spacing="24">
15+
<Button HorizontalAlignment="Left"
16+
VerticalAlignment="Top"
17+
Click="Button_Click"
18+
Content="Send notification" />
19+
20+
<muxc:InfoBar HorizontalAlignment="Left"
21+
VerticalAlignment="Bottom"
22+
IsIconVisible="False">
23+
<interactivity:Interaction.Behaviors>
24+
<behaviors:StackedNotificationsBehavior x:Name="NotificationQueue" />
25+
</interactivity:Interaction.Behaviors>
26+
</muxc:InfoBar>
27+
</StackPanel>
28+
</Page>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using CommunityToolkit.WinUI.Behaviors;
6+
7+
namespace BehaviorsExperiment.Samples;
8+
9+
[ToolkitSample(id: nameof(StackedNotificationsBehaviorToolkitSample), "Stacked Notification Migration", description: $"A sample for showing how to create and use a {nameof(StackedNotificationsBehavior)} custom behavior upgrading from InAppNotification.")]
10+
public sealed partial class StackedNotificationsBehaviorToolkitSample : Page
11+
{
12+
public StackedNotificationsBehaviorToolkitSample()
13+
{
14+
this.InitializeComponent();
15+
}
16+
17+
private void Button_Click(object sender, RoutedEventArgs e)
18+
{
19+
// Show our notification for 2 seconds
20+
NotificationQueue.Show(GetRandomText(), 2000);
21+
}
22+
23+
private static int _current = 0;
24+
25+
private static string GetRandomText() => (_current++ % 4) switch
26+
{
27+
1 => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin bibendum enim at tincidunt. Praesent egestas ipsum ligula, nec tincidunt lacus semper non.",
28+
2 => "Pellentesque in risus eget leo rhoncus ultricies nec id ante.",
29+
3 => "Sed quis nisi quis nunc condimentum varius id consectetur metus. Duis mauris sapien, commodo eget erat ac, efficitur iaculis magna. Morbi eu velit nec massa pharetra cursus.",
30+
_ => "Fusce non quam egestas leo finibus interdum eu ac massa. Quisque nec justo leo. Aenean scelerisque placerat ultrices. Sed accumsan lorem at arcu commodo tristique.",
31+
};
32+
}

0 commit comments

Comments
 (0)