Skip to main content
.NET 8.0+

How to: Display a List of Non-Persistent Objects in a Popup Dialog

  • 5 minutes to read

This example demonstrates how to populate and display a list of objects that are not bound to the database (non-persistent objects). A sample application that stores a list of books will be created in this example. An Action that displays a list of duplicate books in a pop-up window will be added to this application.

Tip

A complete sample project is available in the DevExpress Code Examples database at https://supportcenter.devexpress.com/ticket/details/e980/how-to-display-a-list-of-non-persistent-objects.

  1. Define the Book persistent class.

    [DefaultClassOptions]
    public class Book : BaseObject {
        public Book(Session session) : base(session) { }
        public string Title {
            get { return GetPropertyValue<string>(nameof(Title)); }
            set { SetPropertyValue<string>(nameof(Title), value); }
        }
    }
    

    The Book class, as its name implies, is used to represent books. It inherits BaseObject, and thus it is persistent. It contains a single Title property, which stores a book’s title.

  2. Define two non-persistent classes - Duplicate and DuplicatesList.

    [DomainComponent]
    public class Duplicate {
        [Browsable(false), DevExpress.ExpressApp.Data.Key]
        public int Oid;
        public string Title { get; set; }
        public int Count { get; set; }
    }
    [DomainComponent]
    public class DuplicatesList {
        private BindingList<Duplicate> duplicates;
        public DuplicatesList() {
            duplicates = new BindingList<Duplicate>();
        }
        public BindingList<Duplicate> Duplicates { get { return duplicates; } }
    }
    

    Note

    The INotifyPropertyChanged, IXafEntityObject and IObjectSpaceLink interface implementations were omitted in this example. However, it is recommended to support these interfaces in real-world applications (see The Importance of Property Change Notifications for Automatic UI Updates and Non-Persistent Objects).

    These classes are not inherited from an XPO base persistent class, and are not added to the Entity Framework Core data model. As a result, they are not persistent. Use the DomainComponentAttribute to add such classes to the Application Model. This affects application UI construction.

    The Duplicate non-persistent class has three public properties - Title, Count, and Id. The Title property stores the title of a book. The Count property stores the total number of books with the title specified by the Title property. Id is a key property. A key property is required in a non-persistent class for correct ListView operation. To specify a key property, use the KeyAttribute. The DuplicatesList non-persistent class aggregates the duplicates via the Duplicates collection property of the BindingList<Duplicate> type.

  3. Create the following ShowDuplicateBooksController View Controller.

    public class ShowDuplicateBooksController : ObjectViewController<ListView, Book> {
        public ShowDuplicateBooksController() {
            PopupWindowShowAction showDuplicatesAction = 
                new PopupWindowShowAction(this, "ShowDuplicateBooks", "View");
            showDuplicatesAction.CustomizePopupWindowParams += showDuplicatesAction_CustomizePopupWindowParams;
        }
        void showDuplicatesAction_CustomizePopupWindowParams(object sender, CustomizePopupWindowParamsEventArgs e) {
            Dictionary<string, int> dictionary = new Dictionary<string, int>();
            foreach(Book book in View.CollectionSource.List) {
                if(!string.IsNullOrEmpty(book.Title)) {
                    if(dictionary.ContainsKey(book.Title)) {
                        dictionary[book.Title]++;
                    }
                    else 
                        dictionary.Add(book.Title, 1);
                }
            }
            var nonPersistentOS = Application.CreateObjectSpace(typeof(DuplicatesList));
            DuplicatesList duplicateList =nonPersistentOS.CreateObject<DuplicatesList>();
            int duplicateId = 0;
            foreach(KeyValuePair<string, int> record in dictionary) {
                if (record.Value > 1) {
                    var dup = nonPersistentOS.CreateObject<Duplicate>();
                    dup.Id = duplicateId;
                    dup.Title = record.Key;
                    dup.Count = record.Value;
                    duplicateList.Duplicates.Add(dup);
                    duplicateId++;
                }
            }
            nonPersistentOS.CommitChanges();
            DetailView detailView = Application.CreateDetailView(nonPersistentOS, duplicateList);
            detailView.ViewEditMode = DevExpress.ExpressApp.Editors.ViewEditMode.Edit;
            e.View = detailView;
            e.DialogController.SaveOnAccept = false;
            e.DialogController.CancelAction.Active["NothingToCancel"] = false;
        }
    }
    

    This Controller inherits ObjectViewController<ListView, Book>, and thus, targets List Views that display Books. In the Controller’s constructor, the ShowDuplicateBooks PopupWindowShowAction is created. In the Action’s PopupWindowShowAction.CustomizePopupWindowParams event handler, the Books are iterated to find the duplicates. For each duplicate book found, the Duplicate object is instantiated and added to the DuplicatesList.Duplicates collection. Note that a unique key value (Id) is assigned for each Duplicate. Finally, a DuplicatesList Detail View is created and passed to the handler’s CustomizePopupWindowParamsEventArgs.View parameter. As a result, a DuplicatesList object is displayed in a pop-up window when a user clicks ShowDuplicateBooks.

The following images illustrate the implemented Action and its pop-up window.

Windows Forms
ShowDuplicateBooksWin

ASP.NET Web Forms
ShowDuplicateBooksWeb

Blazor
ShowDuplicateBooksBlazor

See Also