Skip to main content
.NET 8.0+

How to: Filter a Link Dialog's List View

  • 7 minutes to read

This topic demonstrates how to filter a List View in a Link Action’s pop-up window. The solution uses the DataSourcePropertyAttribute and a data source collection generated on the fly. You can apply this attribute in code or in the Application Model.

Note

You can use DataSourcePropertyAttribute and DataSourceCriteriaAttribute to filter Lookup Property Editor List Views. For more information, refer to the following topic: How to: Implement Cascading Filtering for Lookup List Views.

Implement Business Objects

  1. In the YourSolutionName.Module\BusinessObjects folder, create the following classes: Employee, Position, and DemoTask. Replace the autogenerated code with the following class declarations:

    • YourSolutionName.Module\BusinessObjects\Employee.cs

      using DevExpress.Persistent.Base;
      using DevExpress.Persistent.BaseImpl.EF;
      using System.Collections.ObjectModel;
      
      namespace YourSolutionName.Module.BusinessObjects {
         [DefaultClassOptions]
         public class Employee : BaseObject {
            public virtual String FirstName { get; set; }
            public virtual String LastName { get; set; }
            public String FullName {
               get { return ObjectFormatter.Format("{FirstName} {LastName}", 
                   this, EmptyEntriesMode.RemoveDelimiterWhenEntryIsEmpty);
               }
            }
            public virtual Position Position { get; set; }
            public virtual IList<DemoTask> Tasks { get; set; } = new ObservableCollection<DemoTask>();
         }
      }
      
      // Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
      
    • YourSolutionName.Module\BusinessObjects\DemoTask.cs

      using DevExpress.Persistent.Base;
      using DevExpress.Persistent.BaseImpl.EF;
      using System.Collections.ObjectModel;
      
      namespace YourSolutionName.Module.BusinessObjects {
      
         [DefaultClassOptions]
         public class DemoTask : BaseObject {
            public virtual String Subject { get; set; }
            public virtual Priority Priority { get; set; }
            public virtual IList<Employee> Employees { get; set; } = new ObservableCollection<Employee>();
         }
      
         public enum Priority {
            Low = 0,
            Normal = 1,
            High = 2
         }
      }
      
      // Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
      
    • YourSolutionName.Module\BusinessObjects\Position.cs

      using DevExpress.Persistent.Base;
      using DevExpress.Persistent.BaseImpl.EF;
      using System.Collections.ObjectModel;
      
      namespace YourSolutionName.Module.BusinessObjects {
      
         [DefaultClassOptions]
         [DefaultProperty(nameof(Title))]
         public class Position : BaseObject {
            public virtual string Title { get; set; }
         }
      
      }
      
      // Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
      

      Tip

      If your application uses Entity Framework Core, register the newly created business classes in the DbContext and update the database schema. For more information, refer to the following topic: Implement a Data Model: Basics.

  2. Run the application. Create several objects of each type. Make sure that there is at least one high-priority task.

  3. Open an Employee object and click the Link Action in the Demo Tasks group. The pop-up window displays all available DemoTask objects.

    ASP.NET Core Blazor
    Link Action's Pop-up Window in XAF ASP.NET Core Blazor Application, DevExpress
    Windows Forms
    Link Action's Pop-up Window in XAF Windows Forms Application, DevExpress

This scenario shows how to populate the Link Action’s List View in the following conditions:

  • The Link List View filter applies only when the current Employee has its Position property set to "Manager". In all other instances, the List View displays all existing DemoTask objects.
  • You can only assign high-priority tasks to managers.
  1. Navigate to the Employee class and replace its declaration with the following code snippet that introduces an additional collection for the Tasks property. This collection is refreshed every time you change the Priority property’s value.

    using DevExpress.ExpressApp;
    using DevExpress.Persistent.Base;
    using DevExpress.Persistent.BaseImpl.EF;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace YourSolutionName.Module.BusinessObjects {
       [DefaultClassOptions]
       public class Employee : BaseObject {
          public Employee() {
                ((INotifyPropertyChanged)this).PropertyChanged += Employee_PropertyChanged;
          }
    
          private void Employee_PropertyChanged(object sender, PropertyChangedEventArgs e) {
                if (e.PropertyName == nameof(DemoTask)) {
                   RefreshAvailableTasks();
                }
          }
          public virtual String FirstName { get; set; }
          public virtual String LastName { get; set; }
          public String FullName {
                get { return ObjectFormatter.Format("{FirstName} {LastName}", 
                    this, EmptyEntriesMode.RemoveDelimiterWhenEntryIsEmpty);
                }
          }
    
          [DataSourceProperty(nameof(AvailableTasks))]
          public virtual ObservableCollection<DemoTask> Tasks { get; set; } = new ObservableCollection<DemoTask>();
    
          private readonly ObservableCollection<DemoTask> availableTasks = new ObservableCollection<DemoTask>();
    
          // Prohibit the AvailableTasks collection
          // from being displayed in the UI as a property.
          [NotMapped, Browsable(false)]
          public virtual IList<DemoTask> AvailableTasks {
                get {
                   if (availableTasks == null) {
                      // Filter the retrieved collection according to the specified conditions 
                      RefreshAvailableTasks();
                   }
                   // Return the filtered collection of DemoTask objects 
                   return availableTasks;
                }
          }
    
          private void RefreshAvailableTasks() {
    
                var os = ((IObjectSpaceLink)this).ObjectSpace;
                ObservableCollection<DemoTask> available = new ObservableCollection<DemoTask>();
    
                // Process the situation when there are no tasks.
                if (availableTasks == null)
                   return;
                // Display only high priority tasks if the employee is a manager.
                if ((Position != null) && (Position.Title == "Manager")) {                
                   available = new ObservableCollection<DemoTask>(os.GetObjectsQuery<DemoTask>().Where(d => d.Priority == Priority.High).ToList());
                }
                else {
                   // Remove the applied filter.
                   available.Clear();
                }
                if (available != null) {
                   RefreshAvailableTasks(available);
                }
          }
    
          private void RefreshAvailableTasks(IEnumerable<DemoTask> demotasks) {
                while (availableTasks.Count > 0) {
                   availableTasks.RemoveAt(availableTasks.Count - 1);
                }
                foreach (var d in demotasks) {
                   availableTasks.Add(d);
                }
          }
    
          private Position position;
    
          public virtual Position Position {
                get { return position; }
                set {
                   position = value;
                   // Refresh the Tasks property data source.
                   RefreshAvailableTasks();
                }
          }
       }
    }
    
    // Make sure that you use options.UseChangeTrackingProxies() and options.UseObjectSpaceLinkProxies() in your DbContext settings.
    
  2. Run the application and navigate to the Detail View of an Employee object whose Position property is set to "Manager". In the Demo Tasks group, click the Link Action. The pop-up window should display only high-priority tasks.

    ASP.NET Core Blazor
    Filtered Link Action's Pop-up Window in XAF ASP.NET Core Blazor Application, DevExpress
    Windows Forms
    Filtered Link Action's Pop-up Window in XAF Windows Forms Application, DevExpress
See Also