Toast Notifications (or simply Toasts) are flat notifications first introduced in Microsoft Windows 8. They pop up in the bottom right corner of your screen and can be accessed through the Windows Action Center. With DevExpress controls, you can display such notifications using the ToastNotificationManager component. Launch the "Outlook Inspired App" demo and let it run for a while to see an example.
You can choose from nine available notification templates, including the Windows 10 "Generic" template that allows you to show user interaction controls like buttons or editors.
Application Shortcut
ToastNotificationManager produces genuine Windows toasts, which means they function in the same way system notifications do: show up even if a related application is closed, can be accessed from the Action Center, have the same color scheme as the operating system, etc. To achieve this, we had to use native Windows API and follow all Microsoft guidelines and requirements. Including the application shortcut requirement.
Now, this application shortcut requirement has proved to be puzzling to some customers. We have recently made a minor design-time improvement and added a new section to the component's documentation page to eliminate any confusion. And, of course, have written this post to ensure no one gets stuck with on this step anymore.
According to the Toast Notifications Overview article by Microsoft, if your app has no shortcut in the Windows Start screen, it cannot show toasts.
Since Start screen shortcuts are kept in the %AppData%\Microsoft\Windows\Start Menu\Programs
folder, you can read this requirement as "to display toasts, add an application shortcut to this folder".
Our component has the "Create Application Shortcut" link in the smart tag menu. After you click this link your app will be able to show notifications.
What some developers are missing, is that the "Create Application Shortcut" command adds the shortcut to their Start screen. Your PC becomes the only machine capable of showing toasts because no one else's Start screen has a shortcut to your app. If you plan to show toasts to your clients, not just yourself, remember to program your application installer to add a shortcut with an AppUserModelID to the %AppData%\Microsoft\Windows\Start Menu\Programs
folder.
Using the installer to add a shortcut is the best solution, and it is safe to recommend it to everyone. However, if for some reason your app has no installer, there's an alternative way - the DevExpress.Data.ShellHelper.TryCreateShortcut
method.
using DevExpress.XtraBars.ToastNotifications;
using DevExpress.Data;
//if there's no app shortcut in the start screen, add it
if (!ShellHelper.IsApplicationShortcutExist("My Test App")) {
ShellHelper.TryCreateShortcut(
applicationId: manager.ApplicationId,
name: "My Test App");
//restart the app
Application.Restart();
}
This way to add app shortcuts is less reliable. First of all, your app may have no permission to write files into system folders. And secondly, you may have noticed the Application.Restart
method in the code snippet above - if the application is already running, adding its shortcut to the Start screen will not enable toasts, you need to restart the entire app.
Activator and COM Server
Windows keeps toast notifications in its Action Center.
Normally, Action Center clears all toasts after a user closes this screen (if a user opens, closes, and opens the Action Center again, it will be empty). Some toasts, however, are capable of staying in the Action Center until a user manually dismisses them. Such toasts remain in the Action Center even after a user logs out and back into Windows. Additionally, these toasts launch their parent applications when clicked. To display such notifications, create a custom Activator - a descendant of the DevExpress.XtraBars.ToastNotifications.ToastNotificationActivator
class.
[Guid("39697E4E-3543-4414-A694-90097B433DC6"), ComVisible(true)]
public class ToastNotificationActivatorCustom : ToastNotificationActivator {
public override void OnActivate(string arguments, Dictionary<string, string> data){
//specify what happens when a user interacts with a toast
}
}
You then need to register this custom Activator: set the component's ApplicationActivator
property at design time or call the RegisterApplicationActivator
method in code.
toastNotificationsManager1.RegisterApplicationActivator(
typeof(ToastNotificationActivatorCustom));
Finally, register a COM Server. To do this, call the DevExpress.Data.ShellHelper.RegisterComServer
method. Note that if you use the ShellHelper class to create an application shortcut, you need to use a TryCreateShortcut
method overload that takes the activatorType parameter. Otherwise, if you use the application installer to add the application shortcut, the installer must also add the HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{-your-GUID-here-}\LocalServer32
registry key with a path to application executable file as a value.
if (!ShellHelper.IsApplicationShortcutExist("My Toast Application")
{
ShellHelper.TryCreateShortcut(
Process.GetCurrentProcess().MainModule.FileName,
toastNotificationsManager1.ApplicationId,
"My Toast Application",
@"D:\Work\Images\_Icons\ico\chain-icon.ico",
typeof(ToastNotificationActivatorCustom));
ShellHelper.RegisterComServer(
Process.GetCurrentProcess().MainModule.FileName,
typeof(ToastNotificationActivatorCustom));
}
GUIDs
When working with toasts, you will need several unique IDs.
- For the component's
ApplicationID
property - For the
ID
property of every notification - For the
Guid
attribute that labels an Activator class
You can mash a keyboard to generate a unique ID, but a more professional approach is to use any online GUID generator (for example, this one) or a generator embedded in Visual Studio ("Tools | Create GUID").
Deliver Critical Notifications
Even when you set up everything correctly, a notification can be not delivered to a user. There can be various reasons for that: an older OS version, turned off notifications in Action Center settings, internal errors, etc. In these emergency cases, you can handle the ToastNotificationsManager.Failed
event to deliver critical messages to users with alternative methods. For instance, show a regular message box.
using DevExpress.XtraBars.ToastNotifications;
using DevExpress.XtraEditors;
void manager_Failed(object sender, ToastNotificationFailedEventArgs e)
{
if ((string)e.NotificationID == "toast_connection_lost_id_das0ud0q94")
{
IToastNotificationProperties undeliveredToast =
toastNotificationsManager1.GetNotificationByID(e.NotificationID);
XtraMessageBox.Show(undeliveredToast.Body, undeliveredToast.Header);
}
}