Ticket T936581
Visible to All Users

Blazor - How to display LookupPropertyEditor's items in a popup window

created 4 years ago

Hi Guys,

i am testing 20.2 Beta Blazor Solution with our existing business objects / modules / database.

Just wondering what is the state about DataAccessMode in Blazor? We usually use DataAccessMode="Server" globally in the Options Node - which leads to an error in blazor detailview if it contains an Lookup Editor. If we use DataAccessMode Client - the performance is quite bad since the lookup is loading ALL records from Database?

Error: System.InvalidOperationException: Kann die Eigenschaft 'DefaultSorting " nicht ändern, wenn die XPCollection nicht im Design oder Initialisierung Modus ist.
at DevExpress.Xpo.XPServerCollectionSource.set_DefaultSorting(String value)
at DevExpress.ExpressApp.Xpo.XPObjectSpace.SetCollectionSorting(Object collection, IList1 sorting) at DevExpress.ExpressApp.CollectionSourceBase.ApplySorting(IList1 sorting)
at DevExpress.ExpressApp.CollectionSourceBase.set_Sorting(IList`1 value)
at DevExpress.ExpressApp.Blazor.Editors.LookupPropertyEditor.InitializeFrame()
at DevExpress.ExpressApp.Blazor.Editors.LookupPropertyEditor.CreateComponentAdapterT
at DevExpress.ExpressApp.Blazor.Editors.LookupPropertyEditor.CreateComponentAdapter()
at DevExpress.ExpressApp.Blazor.Editors.BlazorPropertyEditorBase.CreateControlCore()
at DevExpress.ExpressApp.Editors.ViewItem.CreateControl()
at DevExpress.ExpressApp.CompositeView.CreateViewItemControls()
at DevExpress.ExpressApp.CompositeView.CreateControlsCore()
at DevExpress.ExpressApp.View.CreateControls()

Answers approved by DevExpress Support

created 4 years ago (modified 3 years ago)

Hello Noxe,

We fixed the performance issue described in this ticket:

  • In v20.2.7, the lookup editor loads its data source only when expanded.
  • In v21.1.2+, the lookup editor also supports partial data loading in Queryable mode. This mode is enabled in lookup List Views by default. Please refer to the following help topic for additional information: List View Data Access Modes.

The workaround described below is no longer required for performance optimization. However, it can be useful if you need to show a fully-functional ListView in a popup window. I updated the ticket's subjects accordingly.

How to show additional buttons

With v20.2.4, you can use a custom editor instead of our LookupPropertyEditor: Implement a Property Editor Based on a Custom Component (Blazor).

Here is an example of how to use a ButtonEdit control that shows a lookup ListView in a popup window:

  1. Add the following class to your Blazor module (SolutionName.Module.Blazor):
C#
using System; using System.Collections.Generic; using DevExpress.Blazor; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Blazor; using DevExpress.ExpressApp.Blazor.Components; using DevExpress.ExpressApp.Blazor.Components.Models; using DevExpress.ExpressApp.Blazor.Editors; using DevExpress.ExpressApp.Blazor.Editors.Adapters; using DevExpress.ExpressApp.Blazor.Editors.Grid; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using Microsoft.AspNetCore.Components; namespace YourSolutionName.Module.Blazor.Editors { [PropertyEditor(typeof(Object), EditorAliases.LookupPropertyEditor, true)] public class SearchLookupPropertyEditor : BlazorPropertyEditorBase, IComplexViewItem { class InternalObjectComponentAdapter : ObjectComponentAdapter { private readonly Func<object, string> getDisplayText; private object value; private EventCallback onClick; public InternalObjectComponentAdapter(ObjectComponentModel componentModel, Func<object, string> getDisplayText) : base(componentModel) { this.getDisplayText = getDisplayText; this.onClick = componentModel.OnClick; } public override object GetValue() { return value; } public override void SetValue(object value) { this.value = value; ComponentModel.DisplayText = getDisplayText(value); } } private BlazorApplication application; private IObjectSpace objectSpace; private LookupEditorHelper helper; public SearchLookupPropertyEditor(Type objectType, IModelMemberViewItem model) : base(objectType, model) { } void IComplexViewItem.Setup(IObjectSpace objectSpace, XafApplication application) { this.objectSpace = objectSpace; this.application = (BlazorApplication)application; if(helper == null) { helper = new LookupEditorHelper(application, objectSpace, MemberInfo.MemberTypeInfo, Model); } } protected override IComponentAdapter CreateComponentAdapter() { return new InternalObjectComponentAdapter(new ObjectComponentModel(), propertyValue => GetDisplayText(propertyValue)); } protected override void OnControlCreated() { base.OnControlCreated(); InitControl(); } protected override void OnCurrentObjectChanged() { base.OnCurrentObjectChanged(); InitControl(); } private void InitControl() { if(Control is ObjectComponentAdapter componentAdapter) { componentAdapter.ComponentModel.CssClass = "search-editor"; SetOpenLookupHandler(componentAdapter, enabled: AllowEdit); } } private void SetOpenLookupHandler(ObjectComponentAdapter adapter, bool enabled) { adapter.ComponentModel.OnClick = enabled ? EventCallback.Factory.Create(this, ComponentModel_OnClick) : EventCallback.Empty; } public override void BreakLinksToControl(bool unwireEventsOnly) { if(Control is ObjectComponentAdapter componentAdapter) { SetOpenLookupHandler(componentAdapter, enabled: false); } base.BreakLinksToControl(unwireEventsOnly); } private void ComponentModel_OnClick() { ShowWindow(); } private void ShowWindow() { if(!IsDisposed) { CompositeObjectSpace popupWindowObjectSpace = (CompositeObjectSpace)objectSpace.CreateNestedObjectSpace(); if (!popupWindowObjectSpace.IsKnownType(helper.LookupObjectType)) { popupWindowObjectSpace.AdditionalObjectSpaces.Add(application.CreateObjectSpace(helper.LookupObjectType)); popupWindowObjectSpace.AutoDisposeAdditionalObjectSpaces = true; } helper.SetObjectSpace(popupWindowObjectSpace); ListView lookupListView = helper.CreateListView(helper.ObjectSpace.GetObject(CurrentObject)); lookupListView.ControlsCreated += (s, e) => { if(((ListView)s).Editor is GridListEditor gridListEditor) { IDxDataGridAdapter dataGridAdapter = gridListEditor.GetDataGridAdapter(); dataGridAdapter.DataGridModel.SelectionMode = DataGridSelectionMode.SingleSelectedDataRow; dataGridAdapter.DataGridSelectionColumnModel.Visible = false; if(PropertyValue != null) { gridListEditor.SetSelectedObjects(new List<object>() { PropertyValue }); // requires v20.2.6+ } } }; application.ShowViewStrategy.ShowViewInPopupWindow(lookupListView, () => OnPopupWindowExecute(lookupListView)); } } private void OnPopupWindowExecute(View popupView) { PropertyValue = objectSpace.GetObject(popupView.CurrentObject); ReadValue(); } protected override RenderFragment CreateViewComponentCore(object dataContext) { DisplayTextModel displayTextModel = new DisplayTextModel(); displayTextModel.DisplayText = GetDisplayText(this.GetPropertyValue(dataContext)); return DisplayTextRenderer.Create(displayTextModel); } private string GetDisplayText(object propertyValue) => helper.GetDisplayText(propertyValue, NullText, DisplayFormat); } }
  1. Add the following style to _Host.cshtml:
CSS
<style type="text/css"> .search-editor .xaf-dx-button-image { mask: url(IImageService/Action_Search) !important; -webkit-mask: url(IImageService/Action_Search) !important; } </style>

As a result, all lookup editors will be substituted with your custom editor.

Clipboard-File-2.png

To change the lookup editor only for particular properties, set the third parameter of the [PropertyEditor] attribute to false and use the PropertyEditorType model property.

    Show previous comments (20)

      hi, Anatol:
      When using DataSourceCriteriaProperty open the search pop up displays no data by default and only when you click the search then the last selected data is not by default selection I debug it and we wrote 1 = 2 to the filtering conditions of LookupListView by default

      Clipboard-File-1.png

      Anatol (DevExpress) 4 years ago

        Hello Chengwei,

        Thank you for the clarification. This behavior is inherited from the WinForms and ASP.NET lookup editors because SearchLookupPropertyEditor uses LookupEditorHelper. Please refer to the following article for additional information: How to: Add a Search Action to Lookup Property Editors and Link Pop-up Windows.

        Vladislav B (DevExpress) a year ago

          In XAF Blazor v23.2.2+, we improved our Lookup Property Editor to better address the following usage scenarios:

          • Quickly search data against a single (or multiple) field - just like XAF Web Forms. To deliver this functionality, our lookup editor includes a Search button, and this button displays a separate Find window with a standard data grid and search controls. This Find window also allows you to create new records using the standard New Action.
          • Use all criteria language features for EF Core and XPO ORM without limitations. Unlike a simple combo box, the Find window hosts the standard data grid with all associated features, including server mode.
          • Open a complete detail form for a related record (currently selected lookup value) using a hyperlink. This feature is helpful for those who do not want to view and edit related details in a separate window (currently provided by the Edit button).
          • UX/UI of link dialogs. In `Auto` mode, these dialogs display all records regardless of `LookupSmallCollectionItemCount`. In Search mode, a helpful message is displayed. The message instructs users to search for related records.

          See: How to: Add a Search Action to Lookup Property Editors and Link Pop-up Windows.

          Clipboard-File-1.png

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.