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
In the YourSolutionName.Module\BusinessObjects folder, create the following classes:
Employee
,Position
, andDemoTask
. 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.
Run the application. Create several objects of each type. Make sure that there is at least one high-priority task.
Open an
Employee
object and click the Link Action in theDemo Tasks
group. The pop-up window displays all availableDemoTask
objects.- ASP.NET Core Blazor
- Windows Forms
Populate the Link Action List View Manually
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 itsPosition
property set to"Manager"
. In all other instances, the List View displays all existingDemoTask
objects. - You can only assign high-priority tasks to managers.
Navigate to the
Employee
class and replace its declaration with the following code snippet that introduces an additional collection for theTasks
property. This collection is refreshed every time you change thePriority
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.
Run the application and navigate to the Detail View of an
Employee
object whosePosition
property is set to"Manager"
. In theDemo Tasks
group, click the Link Action. The pop-up window should display only high-priority tasks.- ASP.NET Core Blazor
- Windows Forms