Cómo mostrar notificaciones con texto, imágenes y botones de acción (enriquecidas) en el área de notificación de Windows, usando C# de Visual Studio .Net. Estas notificaciones se integrarán con el centro de notificaciones del equipo.
- Crear proyecto C# en Visual Studio .Net e instalar Microsoft.Toolkit.Uwp.Notifications.
- Mostrar notificación Toast con texto (título y cuerpo).
- Mostrar notificación Toast con texto e imágenes.
- Ocultar todas las notificaciones.
- Mostrar notificación Toast con imagen y botones de acción.
- Mostrar notificación que captura la pulsación en el cuerpo.
- Las notificaciones quedan integradas con Windows.
- Código completo del formulario principal de la aplicación de ejemplo de notificaciones Toast con C#.
Crear proyecto C# en Visual Studio .Net e instalar Microsoft.Toolkit.Uwp.Notifications
En primer lugar, desde Visual Studio .Net, crearemos un proyecto de tipo Aplicación de Windows Forms y con el lenguaje C#:

Estableceremos el nombre del proyecto y la carpeta donde se guardarán los ficheros:

Es muy importante elegir un .NET compatible con el paquete que usaremos para las notificaciones enriquecidas, que es Microsoft.Toolkit.Uwp.Notifications y requiere de .NET 6 o superior:

Una vez creado nuestro proyecto, instalaremos el paquete Nuget Microsoft.Toolkit.Uwp.Notifications. Para ello, accederemos al menú «Herramientas» – «Administrador de paquetes NuGet» – «Administrar paquetes NuGet para la solución…»:

Pulsaremos en «Examinar» y buscaremos «Microsoft.Toolkit.Uwp.Notifications». Elegiremos el paquete «Microsoft.Toolkit.Uwp.Notifications» en su versión 7.1.3. Pulsaremos en «Instalar»:

Aplicaremos los cambios en la solución:

Aceptaremos los términos de licencia:

El paquete quedará instalado para nuestro proyecto y referenciado para su uso:

Para que el paquete Microsoft.Toolkit.Uwp.Notifications funcione correctamente, nuestro proyecto debe tener la compatibilidad del SO en Windows 10, al menos. Para establecerla, pulsaremos en el menú «Proyecto» y en las propiedades del proyecto:

En «Sistema operativo de destino» elegiremos «Windows 10.0.17763.0»:

Mostrar notificación Toast con texto (título y cuerpo)
Como ejemplo, añadiremos un botón al formulario de la aplicación formNotificaciones.cs, para mostrar una notificación enriquecida simple (solo texto). En el evento Click del botón, añadiremos el siguiente código:
1 2 3 4 5 6 7 8 9 10 |
// Mostrar notificación enriquecida simple (solo texto) private void btNotificacionSimple_Click(object sender, EventArgs e) { new ToastContentBuilder() .AddArgument("IDNotificacion", 1111) .AddText("Esta es una notificación enriquecida de prueba.") .AddText("Aparecerán estas tres líneas en el área de notificación del sistema.") .AddText("La primera línea es el título de la notificación, aparecerá en negrita.") .Show(); } |
Si compilamos la aplicación y pulsamos el botón, mostrará una notificación con este formato:

Dado que estas notificaciones se integran con las del sistema Windows, el usuario podrá interacturar con ellas y decidir si las desactiva, si permanecen en el histórico o si las lee (pulsando sobre ella).
Como se puede apreciar, aparece el icono y el nombre del proyecto, que deberemos añadir convenientemente. Para asignar un icono al proyecto accederemos al menú «Proyecto» y a las propiedades. En «Recursos de Win32», en «Icono», elegiremos un fichero de icono para nuestra aplicación (este será el que se muestre en la notificación enriquecida):

Por su parte, estableceremos el nombre del ensamblado, que será el que aparezca en la barra de título de la notificación enriquecida, a la derecha del icono:

Mostrar notificación Toast con texto e imágenes
También podremos mostrar imágenes en la notificación. Como ejemplo, añadiremos dos imágenes, una encima de la propia notificación y la otra debajo del texto de la notificación. Añadiremos otro botón y le asignaremos este código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Mostrar notificación Toast con texto e imágenes private void btNotificacionImagen_Click(object sender, EventArgs e) { new ToastContentBuilder() .AddArgument("IDNotificacion", 2222) .AddText("Título de la notificación") .AddText("Texto de la notificación.") .AddAttributionText("Pie de la notificación.") // Esto mostrará una imagen debajo del texto de la notificación .AddInlineImage(new Uri(@"D:\pildora_phishing.png")) //Esto mostrará una imagen encima de la notificación .AddHeroImage(new Uri(@"D:\pildora2.png")) // Colocar imagen a la izquierda del texto //.AddAppLogoOverride(new Uri(@"D:\logo.png"), ToastGenericAppLogoCrop.Circle) .SetToastScenario(ToastScenario.Default) .SetToastDuration(ToastDuration.Short) .Show(); } |
Teniendo en cuenta que las imágenes deben existir en la ruta y nombre indicados. Al ejecutar nuestra aplicación y pulsar en el botón para mostrar una notificación Toast con imágenes, aparecerá en el área de notificación con este formato:

Ocultar todas las notificaciones
Si queremos ocultar todas las notificaciones generadas en nuestra aplicación, usaremos:
1 2 3 4 5 6 7 8 9 |
public static void CerrarNotificaciones() { ToastNotificationManagerCompat.History.Clear(); } private void btNotificarBoton_Click(object sender, EventArgs e) { NotificacionConBotones(); } |
Mostrar notificación Toast con imagen y botones de acción
Para mostrar una notificación Toast con imagen y botones de acción, usaremos el siguiente método, que mostrará la notificación con un botón de ejemplo con el texto «Visitar ProyectoA» y otro de «Cerrar»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Mostrar notificación Toast con dos botones de acción public static void NotificacionConBotones() { new ToastContentBuilder() .AddArgument("IDNotificacion", 7777) .AddText("Título de la notificación") .AddText("Texto de la notificación.") .AddAttributionText("Pie de la notificación.") // Esto mostrará una imagen debajo del texto de la notificación .AddInlineImage(new Uri(@"D:\logo.png")) .AddButton(new ToastButton() .SetContent("Visitar ProyectoA") .AddArgument("accion", "visitar") .SetImageUri(new Uri(@"D:\logo.png")) .SetBackgroundActivation()) .AddButton(new ToastButton() .SetContent("Cerrar") .AddArgument("accion", "cerrar") .SetBackgroundActivation()) .SetToastScenario(ToastScenario.Default) .SetToastDuration(ToastDuration.Short) .Show(); } |
Añadiremos el siguiente código al botón correspondiente:
1 2 3 4 5 |
// Mostrar notificación con botones de acción private void btNotificarBoton_Click(object sender, EventArgs e) { NotificacionConBotones(); } |
Los botones de acción necesitan que se capture su pulsación y quede identificado qué botón se ha pulsado, en base al argumento «IDNotificacion» de la notificación, que en el caso anterior tiene valor «7777» y en base al argumento «accion», «visitar» o «accion», «cerrar» de cada botón. Definiremos un método en el mismo fichero formNotificaciones.cs donde hemos definido la notificación con los botones con el siguiente código C#:
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 |
// Capturar evento cuando se pulsa un botón en la ventana de notificación Toast public static void BotonToastPulsado() { ToastNotificationManagerCompat.OnActivated += toastArgs => { ToastArguments args = ToastArguments.Parse(toastArgs.Argument); // Comprobamos si el evento recibido viene de la notificación "7777" (que tiene los botones) if (args.Contains("IDNotificacion")) { if (args["IDNotificacion"] == "7777") { // Si contiene el argumento "accion" es porque se ha pulsado uno de los botones if (args.Contains("accion")) { // Para el botón de acción de "Visitar ProyectoA" if (args["accion"] == "visitar") { MessageBox.Show("Ha pulsado en el botón de Visitar ProyectoA.", "Botón pulsado...", MessageBoxButtons.OK, MessageBoxIcon.Information); string url = "https://www.proyectoa.com"; try { //System.Diagnostics.Process.Start(url); Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); } catch (System.ComponentModel.Win32Exception noBrowser) { if (noBrowser.ErrorCode == -2147467259) MessageBox.Show(noBrowser.Message); } catch (Exception other) { MessageBox.Show(other.Message); } } else if (args["accion"] == "cerrar") // Para el botón de acción de "Cerrar" { MessageBox.Show("Ha pulsado en el botón de cerrar notificación.", "Botón pulsado...", MessageBoxButtons.OK, MessageBoxIcon.Information); CerrarNotificaciones(); } } } } }; } |
Añadiemos un icono al botón «Visitar ProyectoA» para comprobar que también admite iconos.
En el método anterior capturamos la pulsación de los dos botones usando IDNotificacion = «7777», asignando una acción (un bloque de código) a cada botón.
Para que el método BotonToastPulsado funcione, tenemos que modificar el fichero principal de nuestro proyecto, que habitualmente es Program.cs y añadir el siguiente código en la clase internal static class Program:
1 2 3 4 5 6 7 |
[ModuleInitializer] public static void Init() { ApplicationConfiguration.Initialize(); formNotificacion.BotonToastPulsado(); } |
Quedando el fichero Program.cs con el siguiente contenido:
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 |
using System.Runtime.CompilerServices; namespace ProyectoANotificacionesEnriquecidas { internal static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { ApplicationConfiguration.Initialize(); Application.Run(new formNotificacion()); } [ModuleInitializer] public static void Init() { ApplicationConfiguration.Initialize(); formNotificacion.BotonToastPulsado(); } } } |
Si ahora compilamos la aplicación y pulsamos el botón que muestra la notificación con botones:

Obtendremos este resultado:

Siendo los botones «Visitar ProyectoA» y «Cerrar» perfectamente operativos. Si pulsamos en «Visitar ProyectoA», mostrará el mensaje correspondiente y abrirá el navegador web, accediendo a «https://www.proyectoa.com». Cerrará la notificación, asumiendo que se ha «leído»:

Si se pulsa en «Cerrar», mostrará el correspondiente mensaje y cerrará la notificación (dado que se asume que se ha «leído»):

En ambos casos, si se pulsa en alguno de los botones o en la propia notificación, se cerrará y no se almacenará en el histórico de notificaciones. En cambio, si no se interactúa con la notificación, esta se cerrará transcurridos unos segundos y se almacenará en el histórico de notificaciones, como mostramos en el siguiente punto.
Mostrar notificación que captura la pulsación en el cuerpo
Si queremos que cuando el usuario pulse en la propia notificación, tanto mientras se está mostrando como cuando está en el histórico y haga alguna acción podremos usar el mismo mecanismo que para habilitar un botón de acción. O bien añadimos un argumento específico a la notificación para identificarla o bien usamos el mismo argumento que hemos definido para identificar cada conversación «IDNotificacion», este será el que usemos. Añadiremos un botón y le asignaremos el siguiente código (para mostrar una notificación con imagen y que actúe en caso de pulsación por parte del usuario):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Mostrar notificación que aceptará pulsación en el cuerpo y en segundo plano (cuando está en el histórico) private void btNotificacionSegundoPlano_Click(object sender, EventArgs e) { new ToastContentBuilder() .AddArgument("IDNotificacion", 5555) .AddText("Título de la notificación") .AddText("Texto de la notificación.") .AddAttributionText("Pie de la notificación.") // Esto mostrará una imagen debajo del texto de la notificación .AddInlineImage(new Uri(@"D:\pildora_phishing.png")) .SetToastScenario(ToastScenario.Default) .SetToastDuration(ToastDuration.Short) .Show(toast => { toast.ExpirationTime = DateTime.Now.AddMinutes(1); }); } |
Como ejemplo, a la notificación anterior le hemos añadido un tiempo de expiración de un minuto. Una vez transcurrido, desaparecerá del histórico.
En este caso hemos usado el argumento «IDNotificacion» con valor «5555». A continuación añadiremos el método que se ejecutará cuando se pulse sobre la notificación:
1 2 3 4 5 6 7 |
// Método que se ejecutará si se pulsa el cuerpo de la notificación // O si se pulsa estando en el histórico private static void PulsadaNotificacionSegundoPlano() { MessageBox.Show("Has pulsado en la notificación 5555.", "ProyectoA - Notificación...", MessageBoxButtons.OK, MessageBoxIcon.Information); } |
Por último, para capturar la pulsación e identificarla en la notificación «5555» añadiremos el siguiente código al método BotonToastPulsado() definido anteriormente:
1 2 3 4 5 6 |
// Para la notificación que aceptará la pulsación en el cuerpo, tanto // mientras se muestra como cuando está en el histórico if (args["IDNotificacion"] == "5555") { PulsadaNotificacionSegundoPlano(); } |
Si probamos la notificación, cuando se muestra, si se pulsa sobre ella, mostrará el mensaje:

En este caso, si se cierra la aplicación y, posteriormente, el usuario pulsa en la notificación, la aplicación se volverá a abrir.
Las notificaciones quedan integradas con Windows
Al tratarse de notificaciones integradas con el sistema de notificaciones de Windows, el usuario podrá decidir si las oculta, si las desactiva:

O si las muestra o si las consulta en el área de últimas notificaciones:

En el caso de notificaciones con imagen de tipo HeroImage, ésta aparecerá en el histórico de notificaciones, siempre que haya pocas pendientes de lectura:

Código completo del formulario principal de la aplicación de ejemplo de notificaciones Toast con C#
El código completo del formulario principal formNotificaciones.cs de la aplicación de ejemplo que mustra diferentes notificaciones Toast con C#:
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
using Microsoft.Toolkit.Uwp.Notifications; using System.Diagnostics; namespace ProyectoANotificacionesEnriquecidas { public partial class formNotificacion : Form { public formNotificacion() { InitializeComponent(); } // Mostrar notificación enriquecida simple (solo texto) private void btNotificacionSimple_Click(object sender, EventArgs e) { new ToastContentBuilder() .AddArgument("IDNotificacion", 1111) .AddText("Esta es una notificación enriquecida de prueba.") .AddText("Aparecerán estas tres líneas en el área de notificación del sistema.") .AddText("La primera línea es el título de la notificación, aparecerá en negrita.") .Show(); } // Mostrar notificación Toast con texto e imágenes private void btNotificacionImagen_Click(object sender, EventArgs e) { new ToastContentBuilder() .AddArgument("IDNotificacion", 2222) .AddText("Título de la notificación") .AddText("Texto de la notificación.") .AddAttributionText("Pie de la notificación.") // Esto mostrará una imagen debajo del texto de la notificación .AddInlineImage(new Uri(@"D:\pildora_phishing.png")) //Esto mostrará una imagen encima de la notificación .AddHeroImage(new Uri(@"D:\pildora2.png")) // Colocar imagen a la izquierda del texto //.AddAppLogoOverride(new Uri(@"D:\logo.png"), ToastGenericAppLogoCrop.Circle) .SetToastScenario(ToastScenario.Default) .SetToastDuration(ToastDuration.Short) .Show(); } // Cierra todas las notificaciones abiertas y las quita del histórico de Windows private void btQuitarNotificaciones_Click(object sender, EventArgs e) { CerrarNotificaciones(); } // Mostrar notificación con botones de acción private void btNotificarBoton_Click(object sender, EventArgs e) { NotificacionConBotones(); } // Mostrar notificación Toast con dos botones de acción public static void NotificacionConBotones() { new ToastContentBuilder() .AddArgument("IDNotificacion", 7777) .AddText("Título de la notificación") .AddText("Texto de la notificación.") .AddAttributionText("Pie de la notificación.") // Esto mostrará una imagen debajo del texto de la notificación .AddInlineImage(new Uri(@"D:\logo.png")) .AddButton(new ToastButton() .SetContent("Visitar ProyectoA") .AddArgument("accion", "visitar") .SetImageUri(new Uri(@"D:\logo.png")) .SetBackgroundActivation()) .AddButton(new ToastButton() .SetContent("Cerrar") .AddArgument("accion", "cerrar") .SetBackgroundActivation()) .SetToastScenario(ToastScenario.Default) .SetToastDuration(ToastDuration.Short) .Show(); } // Método para cerrar todas las notificaciones y eliminarlas del histórico public static void CerrarNotificaciones() { ToastNotificationManagerCompat.History.Clear(); } // Mostrar notificación que aceptará pulsación en el cuerpo y en segundo plano (cuando está en el histórico) private void btNotificacionSegundoPlano_Click(object sender, EventArgs e) { new ToastContentBuilder() .AddArgument("IDNotificacion", 5555) .AddText("Título de la notificación") .AddText("Texto de la notificación.") .AddAttributionText("Pie de la notificación.") // Esto mostrará una imagen debajo del texto de la notificación .AddInlineImage(new Uri(@"D:\pildora_phishing.png")) .SetToastScenario(ToastScenario.Default) .SetToastDuration(ToastDuration.Short) .Show(toast => { toast.ExpirationTime = DateTime.Now.AddMinutes(1); }); } // Método que se ejecutará si se pulsa el cuerpo de la notificación // O si se pulsa estando en el histórico private static void PulsadaNotificacionSegundoPlano() { MessageBox.Show("Has pulsado en la notificación 5555.", "ProyectoA - Notificación...", MessageBoxButtons.OK, MessageBoxIcon.Information); } // Capturar evento cuando se pulsa un botón en la ventana de notificación Toast public static void BotonToastPulsado() { ToastNotificationManagerCompat.OnActivated += toastArgs => { ToastArguments args = ToastArguments.Parse(toastArgs.Argument); // Comprobamos si el evento recibido viene de la notificación "7777" (que tiene los botones) if (args.Contains("IDNotificacion")) { if (args["IDNotificacion"] == "7777") { // Si contiene el argumento "accion" es porque se ha pulsado uno de los botones if (args.Contains("accion")) { // Para el botón de acción de "Visitar ProyectoA" if (args["accion"] == "visitar") { MessageBox.Show("Ha pulsado en el botón de Visitar ProyectoA.", "Botón pulsado...", MessageBoxButtons.OK, MessageBoxIcon.Information); string url = "https://www.proyectoa.com"; try { //System.Diagnostics.Process.Start(url); Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); } catch (System.ComponentModel.Win32Exception noBrowser) { if (noBrowser.ErrorCode == -2147467259) MessageBox.Show(noBrowser.Message); } catch (Exception other) { MessageBox.Show(other.Message); } } else if (args["accion"] == "cerrar") // Para el botón de acción de "Cerrar" { MessageBox.Show("Ha pulsado en el botón de cerrar notificación.", "Botón pulsado...", MessageBoxButtons.OK, MessageBoxIcon.Information); CerrarNotificaciones(); } } } // Para la notificación que aceptará la pulsación en el cuerpo, tanto // mientras se muestra como cuando está en el histórico if (args["IDNotificacion"] == "5555") { PulsadaNotificacionSegundoPlano(); } } }; } } } |