Display and Edit Simple Type Values in a Lookup Property Editor
- 9 minutes to read
This help topic describes how to allow end users to select a property value of a simple type (string, integer, enumeration, and so on) in a lookup editor.
Important
The examples demonstrated in this help topic require calculation on the client side and do not support Server, ServerView, InstantFeedback, and InstantFeedbackView modes.
Populate the Lookup Editor with Values from Another Property
This section demonstrates how to display user-friendly strings instead of simple type values in a lookup editor.
Scenario
Suppose you have the following class and want to display user-friendly strings for the Position integer property:
File: MySolution.Module\BusinessObjects\DemoClass.cs(.vb).
using DevExpress.Persistent.Base;
using System.ComponentModel.DataAnnotations;
//...
[DefaultClassOptions]
public class DemoClass : BaseObject {
public virtual int Position { get; set; }
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
Solution
Apply the Browsable attribute to the Position property to hide its editor from the UI:
using System.ComponentModel; //... public class DemoClass : BaseObject { //... [Browsable(false)] public virtual int Position { get; set; } } // Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
Create an additional PositionPropertyWrapper class that is a wrapper for the DemoClass.Position property. Apply the DomainComponent attribute to this class to make it non-persistent. In PositionPropertyWrapper, the Key property stores the original integer values, and the DisplayName property returns their user-friendly string representations.
File: MySolution.Module\BusinessObjects\PositionPropertyWrapper.cs(.vb).
using DevExpress.ExpressApp.DC; //... [DomainComponent, XafDefaultProperty(nameof(PositionName))] public class PositionPropertyWrapper { private int _key; private string _positionName; public PositionPropertyWrapper(string positionName, int key) { this._key = key; this._positionName = positionName; } [DevExpress.ExpressApp.Data.Key] public int Key { get { return _key; } } public string PositionName { get { return _positionName; } } }
Important
Use the Key attribute from the DevExpress.ExpressApp.Data namespace only (not from the System.ComponentModel.DataAnnotations or DevExpress.Xpo namespaces). This attribute is required for XAF ASP.NET Web Forms and ASP.NET Core Blazor applications.
Extend DemoClass with the PositionDataSource property that stores the collection of non-persistent PositionPropertyWrapper objects. The Position lookup editor displays these objects. Apply the Browsable attribute to the PositionDataSource property to hide its editor from the UI:
File: MySolution.Module\BusinessObjects\DemoClass.cs(.vb).
using System.ComponentModel; using System.ComponentModel.Annotations; //... public class DemoClass : BaseObject { //... private BindingList<PositionPropertyWrapper> _positionDataSource; [NotMapped, Browsable(false)] public BindingList<PositionPropertyWrapper> PositionDataSource { get { if (_positionDataSource == null) { _positionDataSource = new BindingList<PositionPropertyWrapper>(); for (int i = 0; i < 5; i++) { _positionDataSource.Add(new PositionPropertyWrapper("Position" + i.ToString(), i)); } } return _positionDataSource; } } } // Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
Extend DemoClass with the non-persistent PositionWrapper property of the PositionPropertyWrapper type to update the persistent Position property. Apply the DataSourceProperty attribute to PositionWrapper to populate the lookup editor data source:
using System.Linq; using System.ComponentModel.Annotations; // ... public class DemoClass : BaseObject { // ... private PositionPropertyWrapper _positionPropertyWrapper; [NotMapped, XafDisplayName("Position")] [DataSourceProperty(nameof(PositionDataSource))] public PositionPropertyWrapper PositionWrapper { get { if (_positionPropertyWrapper == null || _positionPropertyWrapper.Key != Position) { _positionPropertyWrapper = PositionDataSource.FirstOrDefault(i => i.Key == Position); } return _positionPropertyWrapper; } set { _positionPropertyWrapper = value; Position = value.Key; } } } // Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
Optional. You can also hide the lookup editor’s Clear button for a non-nullable PositionWrapper property. To do this, set its AllowClear property to false in the Model Editor or apply ModelDefaultAttribute to PositionWrapper:
Populate the Lookup Editor with Persistent Business Objects
This section demonstrates how to display a lookup editor with persistent objects instead of a simple type editor. Use this technique if you have legacy databases and cannot modify their schemas to create associations between tables.
Scenario
Suppose you have the following classes and want to display the Position.Title lookup editor instead of the DemoClass.PositionTitle string editor.
using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using DevExoress.Persistent.BaseImpl.EF;
using System.ComponentModel.DataAnnotations;
//...
[DefaultClassOptions]
public class DemoClass : BaseObject {
public virtual string PositionTitle { get; set; }
}
[DefaultClassOptions, XafDefaultProperty(nameof(Title))]
public class Position : BaseObject {
public virtual string Title { get; set; }
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.
Solution
Apply the Browsable attribute to the PositionTitle property to hide its editor from the UI:
Create a non-persistent wrapper property (LookupPropertyForDisplay) to fetch records from the Position data table:
using DevExpress.Data.Filtering; using DevExpress.ExpressApp.DC; //... public class DemoClass : BaseObject { //... private Position _LookupPropertyForDisplay; [NotMapped, XafDisplayName("Position")] public virtual Position LookupPropertyForDisplay { get { if ((_LookupPropertyForDisplay == null && !string.IsNullOrEmpty(positionTitle)) || (_LookupPropertyForDisplay != null && _LookupPropertyForDisplay.Title != PositionTitle)) { _LookupPropertyForDisplay = ObjectSpace.GetObjectsQuery<Position>().FirstOrDefault(t => t.Title == positionTitle); } return _LookupPropertyForDisplay; } set { _LookupPropertyForDisplay = value; PositionTitle = value != null ? value.Title : string.Empty; } } } // Make sure that you use options.UseChangeTrackingProxies() and options.UseObjectSpaceLinkProxies() in your DbContext settings.
Notes
- You can also filter the Lookup Property Editor data sources as described in the following help topic: How to: Implement Cascading Filtering for Lookup List Views.
Refer to the following help topics for more information on other ways to implement similar tasks:
- How to: Display an Integer Property as an Enumeration
- How to: Implement a Property Editor Based on a Custom Control (WinForms)
- How to: Implement a Property Editor Based on Custom Controls (ASP.NET)
- How to: Implement a Property Editor Based on a Custom Component (Blazor)
- How to: Supply Predefined Values for the String Property Editor Dynamically (WinForms)
- How to: Supply Predefined Values for the String Property Editor Dynamically (ASP.NET)