Skip to content

Commit a21a44f

Browse files
author
msftbot[bot]
authored
Remove lock statements from InAppNotification control (#3368)
## Fixes Remove the `lock` statements used in `InAppNotification` as well as all the timers used to detect when the animation ends. ## PR Type What kind of change does this PR introduce? - Feature - Code style update (formatting) - Refactoring (no functional changes, no api changes) - Sample app changes ## What is the current behavior? The current `InAppNotification` implementation is using a lot of `lock` which are not needed since all the code lives in the UI thread. ## What is the new behavior? The control is no longer using any `lock`. All the notifications are now pushed to `_stackedNotificationOptions` which will control when the notification is displayed. This change allow us to set the appropriate content on the `ContentPresenter` when the control template is applied. WE can also now push directly an `object` content as the notification payload. To make it always work, I've simplified the logic between the `InAppNotification` and its template. This is introducing a breaking change in the notification template. ## PR Checklist Please check if your PR fulfills the following requirements: - [x] Tested code with current [supported SDKs](../readme.md#supported) - [x] Pull Request has been submitted to the documentation repository. Link: [#365](MicrosoftDocs/WindowsCommunityToolkitDocs#365) - [x] Sample in sample app has been added / updated (for bug fixes / features) - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets) - [ ] Tests for the changes have been added (for bug fixes / features) (if applicable) - [ ] Header has been added to all new source files (run *build/UpdateHeaders.bat*) - [ ] Contains **NO** breaking changes The `ContentPresenter` of the `InAppNotification` template must now be named `PART_Presenter`. ## Other information The XAML files have been updated by XAML styler and contains a lot of changes unrelated to this PR.
2 parents 5003f31 + 347efd1 commit a21a44f

File tree

9 files changed

+464
-326
lines changed

9 files changed

+464
-326
lines changed

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationCode.bind

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,29 @@ if (isTemplatePresent && inAppNotificationWithButtonsTemplate is DataTemplate)
4646
ExampleInAppNotification.Show(inAppNotificationWithButtonsTemplate as DataTemplate);
4747
}
4848

49+
// Show notification using an object
50+
<controls:InAppNotification
51+
x:Name="ExampleInAppNotification"
52+
ContentTemplate="{StaticResource MyNotificationDataTemplate}" />
53+
54+
var notificationData = new MyNotificationData("Title", "Message");
55+
ExampleInAppNotification.Show(notificationData, duration: 2000);
56+
4957
// Dismiss notification
5058
ExampleInAppNotification.Dismiss();
5159

5260
// ## C# - Handle button events
5361

5462
private void YesButton_Click(object sender, RoutedEventArgs e)
5563
{
56-
// TODO : Do something when user accepted
64+
// TODO : Do something when user accepted
5765

5866
ExampleInAppNotification.Dismiss();
5967
}
6068

6169
private void NoButton_Click(object sender, RoutedEventArgs e)
6270
{
63-
// TODO : Do something when user refused
71+
// TODO : Do something when user refused
6472

6573
ExampleInAppNotification.Dismiss();
6674
}

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationPage.xaml.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using System;
6-
using System.Windows.Input;
75
using Microsoft.Toolkit.Uwp.UI.Controls;
86
using Microsoft.Toolkit.Uwp.UI.Extensions;
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Windows.Input;
910
using Windows.UI.Xaml;
1011
using Windows.UI.Xaml.Controls;
1112

@@ -57,6 +58,15 @@ private void Load()
5758
_exampleInAppNotification?.Show(GetRandomText(), NotificationDuration);
5859
});
5960

61+
SampleController.Current.RegisterNewCommand("Show notification with object", (sender, args) =>
62+
{
63+
_exampleVSCodeInAppNotification?.Dismiss();
64+
SetDefaultControlTemplate();
65+
66+
var random = new Random();
67+
_exampleInAppNotification?.Show(new KeyValuePair<int, string>(random.Next(1, 10), GetRandomText()), NotificationDuration);
68+
});
69+
6070
SampleController.Current.RegisterNewCommand("Show notification with buttons (without DataTemplate)", (sender, args) =>
6171
{
6272
_exampleVSCodeInAppNotification?.Dismiss();

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/InAppNotification/InAppNotificationXaml.bind

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@
153153
<ColumnDefinition Width="Auto" />
154154
</Grid.ColumnDefinitions>
155155

156-
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
156+
<ContentPresenter x:Name="PART_Presenter"
157+
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
157158
HorizontalContentAlignment="Stretch"
158159
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
159160
VerticalContentAlignment="Center"
@@ -333,7 +334,8 @@
333334
<ColumnDefinition Width="Auto" />
334335
</Grid.ColumnDefinitions>
335336

336-
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
337+
<ContentPresenter x:Name="PART_Presenter"
338+
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
337339
HorizontalContentAlignment="Stretch"
338340
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
339341
VerticalContentAlignment="Center"
@@ -376,7 +378,17 @@
376378
AnimationDuration="@[AnimationDuration:TimeSpan:100:0-5000]"
377379
VerticalOffset="@[VerticalOffset:DoubleSlider:100.0:-200.0-200.0]"
378380
HorizontalOffset="@[HorizontalOffset:DoubleSlider:0.0:-200.0-200.0]"
379-
StackMode="@[StackMode:Enum:StackMode.Replace]" />
381+
StackMode="@[StackMode:Enum:StackMode.Replace]">
382+
<controls:InAppNotification.ContentTemplate>
383+
<DataTemplate>
384+
<StackPanel>
385+
<TextBlock Text="{Binding Value}" Margin="0,0,0,8" />
386+
<TextBlock Text="{Binding Key}" Style="{ThemeResource CaptionTextBlockStyle}" Opacity="0.8" />
387+
</StackPanel>
388+
</DataTemplate>
389+
</controls:InAppNotification.ContentTemplate>
390+
</controls:InAppNotification>
391+
380392

381393
<controls:InAppNotification x:Name="ExampleCustomInAppNotification"
382394
Style="{StaticResource MSEdgeNotificationTemplate_NoDismissButton}"

Microsoft.Toolkit.Uwp.UI.Controls/InAppNotification/InAppNotification.Constants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,10 @@ public partial class InAppNotification
2828
/// Key of the UI Element that dismiss the control
2929
/// </summary>
3030
private const string DismissButtonPart = "PART_DismissButton";
31+
32+
/// <summary>
33+
/// Key of the UI Element that will display the notification content.
34+
/// </summary>
35+
private const string ContentPresenterPart = "PART_Presenter";
3136
}
3237
}

Microsoft.Toolkit.Uwp.UI.Controls/InAppNotification/InAppNotification.Events.cs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ public partial class InAppNotification
3535
/// </summary>
3636
public event InAppNotificationClosedEventHandler Closed;
3737

38+
private static void AutomateTextNotification(AutomationPeer peer, string message)
39+
{
40+
if (peer != null)
41+
{
42+
peer.SetFocus();
43+
peer.RaiseNotificationEvent(
44+
AutomationNotificationKind.Other,
45+
AutomationNotificationProcessing.ImportantMostRecent,
46+
StringExtensions.GetLocalized("WindowsCommunityToolkit_InAppNotification_Events_NewNotificationMessage", "/Microsoft.Toolkit.Uwp.UI.Controls/Resources") + message,
47+
Guid.NewGuid().ToString());
48+
}
49+
}
50+
3851
private void DismissButton_Click(object sender, RoutedEventArgs e)
3952
{
4053
Dismiss(InAppNotificationDismissKind.User);
@@ -45,44 +58,37 @@ private void DismissTimer_Tick(object sender, object e)
4558
Dismiss(InAppNotificationDismissKind.Timeout);
4659
}
4760

48-
private void OpenAnimationTimer_Tick(object sender, object e)
61+
private void OnCurrentStateChanged(object sender, VisualStateChangedEventArgs e)
4962
{
50-
lock (_openAnimationTimer)
63+
switch (e.NewState.Name)
5164
{
52-
_openAnimationTimer.Stop();
53-
Opened?.Invoke(this, EventArgs.Empty);
54-
SetValue(AutomationProperties.NameProperty, StringExtensions.GetLocalized("WindowsCommunityToolkit_InAppNotification_NameProperty", "/Microsoft.Toolkit.Uwp.UI.Controls/Resources"));
55-
if (ContentTemplateRoot != null)
56-
{
57-
var peer = FrameworkElementAutomationPeer.CreatePeerForElement(ContentTemplateRoot);
58-
if (Content?.GetType() == typeof(string))
59-
{
60-
AutomateTextNotification(peer, Content.ToString());
61-
}
62-
}
65+
case StateContentVisible:
66+
OnNotificationVisible();
67+
break;
68+
case StateContentCollapsed:
69+
OnNotificationCollapsed();
70+
break;
6371
}
6472
}
6573

66-
private void AutomateTextNotification(AutomationPeer peer, string message)
74+
private void OnNotificationVisible()
6775
{
68-
if (peer != null)
76+
Opened?.Invoke(this, EventArgs.Empty);
77+
SetValue(AutomationProperties.NameProperty, StringExtensions.GetLocalized("WindowsCommunityToolkit_InAppNotification_NameProperty", "/Microsoft.Toolkit.Uwp.UI.Controls/Resources"));
78+
if (ContentTemplateRoot != null)
6979
{
70-
peer.SetFocus();
71-
peer.RaiseNotificationEvent(
72-
AutomationNotificationKind.Other,
73-
AutomationNotificationProcessing.ImportantMostRecent,
74-
StringExtensions.GetLocalized("WindowsCommunityToolkit_InAppNotification_Events_NewNotificationMessage", "/Microsoft.Toolkit.Uwp.UI.Controls/Resources") + message,
75-
Guid.NewGuid().ToString());
80+
var peer = FrameworkElementAutomationPeer.CreatePeerForElement(ContentTemplateRoot);
81+
if (Content?.GetType() == typeof(string))
82+
{
83+
AutomateTextNotification(peer, Content.ToString());
84+
}
7685
}
7786
}
7887

79-
private void ClosingAnimationTimer_Tick(object sender, object e)
88+
private void OnNotificationCollapsed()
8089
{
81-
lock (_closingAnimationTimer)
82-
{
83-
_closingAnimationTimer.Stop();
84-
Closed?.Invoke(this, new InAppNotificationClosedEventArgs(_lastDismissKind));
85-
}
90+
Closed?.Invoke(this, new InAppNotificationClosedEventArgs(_lastDismissKind));
91+
Visibility = Visibility.Collapsed;
8692
}
8793
}
8894
}

0 commit comments

Comments
 (0)