How to: Show Various Notifications for Multiple Users

When you implement notifications in your application, one instance of notification class is created and displayed to each user by default. In the case that one user modifies this notification, for example using the Snooze or Dismiss Action, this notification is modified for all users. Create various notifications to multiple users as described in this topic to allow users use these Actions without collisions.

Note

Assume you have an application with the Security System enabled. The MyNotification class implements the ISupportNotifications interface and exposes the AssignedTo and MyTask properties.

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using DevExpress.Persistent.Base.General;
using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
//...
public class MyNotification : ISupportNotifications {
    public int Id { get; private set; }
    public virtual MyTask MyTask { get; set; }
    public virtual PermissionPolicyUser AssignedTo { get; set; }
    private DateTime? alarmTime;
    public DateTime? AlarmTime {
        get {
            return alarmTime;
        }
        set {
            alarmTime = value;
            if (value == null) {
                IsPostponed = false;
            }
        }
    }
    [Browsable(false), NotMapped]
    public object UniqueId {
        get { return Id; }
    }
    [Browsable(false)]
    public bool IsPostponed { get; set; }
    [Browsable(false)]
    public string NotificationMessage { get { return MyTask.Subject; } }
}

The MyTask property is an object of the custom MyTask type. The MyTask class has the MyNotifications aggregated collection of notifications that is a part of the one-to-many relationship.

using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using System.Collections.Generic;
using System.ComponentModel;
[DefaultClassOptions]
public class MyTask {
    public MyTask() {
        MyNotifications = new List<MyNotification>();
    }
    [Browsable(false)]
    public int Id { get; private set; }
    public string Subject { get; set; }
    [Aggregated]
    public virtual IList<MyNotification> MyNotifications { get; set; }
}
Note

If you use the Event class from the Business Class Library with the Scheduler Module instead of the custom ISupportNotifications object, the Scheduler features (for example, the RecurringReminder functionality) are unworkable. To avoid this, you should create a separate Event instance for each user.

Edit the Module.cs (Module.vb) file. In the overridden ModuleBase.Setup method, subscribe to the XafApplication.LoggedOn event. In this event handler, get the NotificationsModule instance and subscribe to the DefaultNotificationsProvider.CustomizeNotificationCollectionCriteria event.

using DevExpress.Data.Filtering;
using DevExpress.ExpressApp.Notifications;
using DevExpress.Persistent.Base.General;
// ...
public override void Setup(XafApplication application) {
    base.Setup(application);
    application.LoggedOn += new EventHandler<LogonEventArgs>(application_LoggedOn);
}
void application_LoggedOn(object sender, LogonEventArgs e) {
   NotificationsModule notificationsModule = Application.Modules.FindModule<NotificationsModule>();
   DefaultNotificationsProvider notificationsProvider = notificationsModule.DefaultNotificationsProvider;
   notificationsProvider.CustomizeNotificationCollectionCriteria += notificationsProvider_CustomizeNotificationCollectionCriteria;
}
void notificationsProvider_CustomizeNotificationCollectionCriteria(
    object sender, CustomizeCollectionCriteriaEventArgs e) {
    if (e.Type == typeof(MyNotification)) {
        e.Criteria = CriteriaOperator.Parse("AssignedTo is null || AssignedTo.Id == CurrentUserId()");
    }
}

As a result, various notifications display for different users if the AssignedTo value refers to the user or same notification for all users if the AssignedTo value is empty.

NotificationForAdminNotificationForUser

Create the Controller which is a WinNotificationsMessageListViewController descendant in a WinForms application or WebNotificationsMessageListViewController in an ASP.NET application if you want to open the corresponding MyTask Detail View when double clicking a notification in the notification window. The example below demonstrates this Controller implementation for the WinForms application.

using System;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Notifications.Win;
//...
public class MyWinNotificationsMessageListViewController : WinNotificationsMessageListViewController {
    protected override View CreateDetailView() {
        Object obj = ViewCurrentObject.NotificationSource;
        if(ViewCurrentObject.NotificationSource is MyNotification) {
            obj = ((MyNotification)ViewCurrentObject.NotificationSource).MyTask;
        }
        IObjectSpace objectSpace = Application.CreateObjectSpace(obj.GetType());
        Object objectInTargetObjectSpace = objectSpace.GetObject(obj);
        View view = Application.CreateDetailView(objectSpace, objectInTargetObjectSpace);
        ProcessDetailView(view);
        return view;
    }
}

NotificationWindow_TaskDetailView

If you need to delete a notification when a user dismisses it, create a new ObjectViewController<ViewType, ObjectType> as demonstrated below.

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Notifications;
using DevExpress.Persistent.Base.General;
//...
public class DeleteOnDismissController : ObjectViewController<DetailView, NotificationsObject> {
    private NotificationsService service;
    protected override void OnActivated() {
        base.OnActivated();
        service = Application.Modules.FindModule<NotificationsModule>().NotificationsService;
        NotificationsDialogViewController notificationsDialogViewController = 
Frame.GetController<NotificationsDialogViewController>();
        if (service != null && notificationsDialogViewController != null) {
            notificationsDialogViewController.Dismiss.Executing += Dismiss_Executing;
            notificationsDialogViewController.Dismiss.Executed += Dismiss_Executed;
        }
    }
    protected override void OnDeactivated() {
        NotificationsDialogViewController notificationsDialogViewController = 
Frame.GetController<NotificationsDialogViewController>();
        if(notificationsDialogViewController != null) {
            notificationsDialogViewController.Dismiss.Executing -= Dismiss_Executing;
            notificationsDialogViewController.Dismiss.Executed -= Dismiss_Executed;
        }
        base.OnDeactivated();
    }
    private void Dismiss_Executing(object sender, System.ComponentModel.CancelEventArgs e) {
        service.ItemsProcessed += Service_ItemsProcessed;
    }
    private void Service_ItemsProcessed(object sender, 
DevExpress.Persistent.Base.General.NotificationItemsEventArgs e) {
        IObjectSpace space = Application.CreateObjectSpace(typeof(MyNotification));
        foreach(INotificationItem item in e.NotificationItems) {
            if(item.NotificationSource is MyNotification) {
                space.Delete(space.GetObject(item.NotificationSource));
            }
        }
        space.CommitChanges();
    }
    private void Dismiss_Executed(object sender, 
DevExpress.ExpressApp.Actions.ActionBaseEventArgs e) {
        service.ItemsProcessed -= Service_ItemsProcessed;
    }
}