■ AppNotificationManager 클래스의 Default 정적 속성을 사용해 토스트 알림(Toast Notification)을 표시하는 방법을 보여준다.
※ 비주얼 스튜디오에서 TestProject(Unpackaged) 모드로 빌드한다.
※ TestProject.csproj 프로젝트 파일에서 WindowsPackageType 태그를 None으로 추가했다.
▶ TestProject.csproj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion> <RootNamespace>TestProject</RootNamespace> <ApplicationManifest>app.manifest</ApplicationManifest> <Platforms>x86;x64;ARM64</Platforms> <RuntimeIdentifiers Condition="$([MSBuild]::GetTarg etFrameworkVersion('$(TargetFramework)')) >= 8">win-x86;win-x64;win-arm64</RuntimeIdentifiers> <RuntimeIdentifiers Condition="$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)')) < 8">win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers> <PublishProfile>win-$(Platform).pubxml</PublishProfile> <UseWinUI>true</UseWinUI> <EnableMsixTooling>true</EnableMsixTooling> <WindowsPackageType>None</WindowsPackageType> <WindowsAppSDKSelfContained>True</WindowsAppSDKSelfContained> </PropertyGroup> <ItemGroup> <Content Include="Assets\SplashScreen.scale-200.png" /> <Content Include="Assets\LockScreenLogo.scale-200.png" /> <Content Include="Assets\Square150x150Logo.scale-200.png" /> <Content Include="Assets\Square44x44Logo.scale-200.png" /> <Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" /> <Content Include="Assets\StoreLogo.png" /> <Content Include="Assets\Wide310x150Logo.scale-200.png" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240627000" /> <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1" /> <Manifest Include="$(ApplicationManifest)" /> </ItemGroup> <!-- Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging Tools extension to be activated for this project even if the Windows App SDK Nuget package has not yet been restored. --> <ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'"> <ProjectCapability Include="Msix" /> </ItemGroup> <!-- Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution Explorer "Package and Publish" context menu entry to be enabled for this project even if the Windows App SDK Nuget package has not yet been restored. --> <PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'"> <HasPackageAndPublishMenu>true</HasPackageAndPublishMenu> </PropertyGroup> </Project> |
▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <Page x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" FontFamily="나눔고딕코딩" FontSize="16"> <Button Name="testButton" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="10" Content="테스트" /> </Page> |
▶ MainPage.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
using System; using System.IO; using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.Windows.AppNotifications; namespace TestProject; /// <summary> /// 메인 페이지 /// </summary> public sealed partial class MainPage : Page { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 디스패처 큐 /// </summary> private DispatcherQueue dispatcherQueue; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainPage() /// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent(); this.dispatcherQueue = DispatcherQueue.GetForCurrentThread(); Unloaded += Page_Unloaded; this.testButton.Click += testButton_Click; AppNotificationManager.Default.NotificationInvoked += AppNotificationManager_NotificationInvoked; AppNotificationManager.Default.Register(); // 상기 NotificationInvoked 이벤트 핸들러를 먼저 설정하고 등록해야 한다. } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 페이지 언로드시 처리하기 - Page_Unloaded(sender, e) /// <summary> /// 페이지 언로드시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void Page_Unloaded(object sender, RoutedEventArgs e) { AppNotificationManager.Default.NotificationInvoked -= AppNotificationManager_NotificationInvoked; AppNotificationManager.Default.Unregister(); } #endregion #region 테스트 버튼 클릭시 처리하기 - testButton_Click(sender, e) /// <summary> /// 테스트 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void testButton_Click(object sender, RoutedEventArgs e) { string applicationDirectoryPath = Path.GetDirectoryName(AppContext.BaseDirectory); string iconFilePath = applicationDirectoryPath + "\\Assets/WindowIcon.ico"; string payload = @$" <toast launch=""action=ToastClick""> <visual> <binding template=""ToastGeneric""> <text>App Notification</text> <text></text> <image placement=""appLogoOverride"" hint-crop=""circle"" src=""{iconFilePath}"" /> </binding> </visual> <actions> <action content=""Settings"" arguments=""action=Settings""/> </actions> </toast> "; AppNotification appNotification = new AppNotification(payload); AppNotificationManager.Default.Show(appNotification); // appNotification.Id가 0이 아니면 정상적으로 처리된 것을 의미한다. } #endregion #region 앱 알림 관리자 알림 호출시 처리하기 - AppNotificationManager_NotificationInvoked(sender, e) /// <summary> /// 앱 알림 관리자 알림 호출시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void AppNotificationManager_NotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs e) { // NotificationInvoked 이벤트 핸들러가 UI 쓰레드가 아니기 때문에 아래와 같은 처리를 한다. this.dispatcherQueue.TryEnqueue ( DispatcherQueuePriority.Low, () => { ContentDialog dialog = new ContentDialog(); dialog.Content = e.Argument; dialog.CloseButtonText = "닫기"; dialog.DefaultButton = ContentDialogButton.Close; dialog.XamlRoot = this.testButton.XamlRoot; _ = dialog.ShowAsync(); } ); } #endregion } |