-
-
Notifications
You must be signed in to change notification settings - Fork 42
LookupCascade
The LookupCascade
module implements client side Cascading Filtering for Lookup List Views (No ImmediatePostData).
Credits: to the Company (wants anonymity) that sponsor the initial implementation of this module.
This is a ASP.NET module
. There are many solutions for implementing Cascading Filtering for Lookup List Views.
However they require a round trip to the server as the ImmediatePostData attribute must be applied and if your users are on a low speed network (regular 2G) then you will notice a few seconds delay for each round trip.
This package aims to address this problem by serializing your data on the server, compress them and send them to the client where javascript will decompress each time a filtering is performed. Below are the configuration steps.
Assuming you have a domain like:
To filter the Accessory lookup values based on the selected Product you need to follow the next steps in order.
- Assign the
ASPxLookupCascadePropertyEditor
to both the Product and Order to an Order DetailView or ListView. - The module extends the
IModelPropertyEditor
with aLookupCascade
property (visible only if the member uses theASPxLookupCascadePropertyEditor
). Configure the ProductLookupCascade.CascadeMemberViewItem
model attribute to point to the Accessory MemberViewItem. - Configure the
CascadeColumnFilter
to point to thevisible
Product key column found in the Accessory_LookupListView. To hide this key column set the columnClientVisible
in the Accessory_LookupListView. - Optionally set the
Synchronize
attribute to true, so when you chose an Accessory with a blank Product it will fill the matching Product for you. - Configure the LookupViews client datasources using the
Application/ReactiveModules/LookupCascade/ClientDatasource/LookupViews
model node. The module will serialize the participating lookupviews and send them to the client once where the client scripts will then use to cascade and synchronize the editors.
Next is the model describing the above configuration used from the related EayTest on each build.
<Application>
<ReactiveModules>
<LookupCascade>
<ClientDatasource>
<LookupViews>
<ClientDatasourceLookupView Id="Accesories" LookupListView="LookupCascade_Accessory_LookupListView" IsNewNode="True" />
<ClientDatasourceLookupView Id="Products" LookupListView="Product_LookupListView" IsNewNode="True" />
</LookupViews>
</ClientDatasource>
</LookupCascade>
</ReactiveModules>
<Views>
<ListView Id="LookupCascade_Accessory_LookupListView">
<Columns>
<ColumnInfo Id="Product" PropertyName="Product.Oid" Index="2" Caption="Product" ClientVisible="False" IsNewNode="True" Removed="True" />
</Columns>
</ListView>
<DetailView Id="LookupCascade_Order_DetailView">
<Items>
<PropertyEditor Id="Accessory" PropertyEditorType="Xpand.XAF.Modules.LookupCascade.ASPxLookupCascadePropertyEditor" View="LookupCascade_Accessory_LookupListView" />
<PropertyEditor Id="AggregatedOrders" View="LookupCascade_Order_ListView" />
<PropertyEditor Id="Product" PropertyEditorType="Xpand.XAF.Modules.LookupCascade.ASPxLookupCascadePropertyEditor">
<LookupCascade CascadeMemberViewItem="Accessory" CascadeColumnFilter="Product" />
</PropertyEditor>
</Items>
</DetailView>
<ListView Id="LookupCascade_Order_ListView" AllowEdit="True" NewItemRowPosition="Top" DetailViewID="LookupCascade_Order_DetailView">
<Columns>
<ColumnInfo Id="Product" PropertyEditorType="Xpand.XAF.Modules.LookupCascade.ASPxLookupCascadePropertyEditor" SortIndex="0" SortOrder="Ascending">
<LookupCascade Synchronize="True" CascadeMemberViewItem="Accessory" CascadeColumnFilter="Product" />
</ColumnInfo>
<ColumnInfo Id="Accessory" PropertyEditorType="Xpand.XAF.Modules.LookupCascade.ASPxLookupCascadePropertyEditor" View="LookupCascade_Accessory_LookupListView">
<LookupCascade SynchronizeMemberViewItem="Product" SynchronizeMemberLookupColumn="ProductName" />
</ColumnInfo>
</Columns>
</ListView>
</Views>
</Application>
Limitations: The module stores the datasources to the sessionStorage which has a limit of 5mb. However they are compressed so you can store a really large number of objects. The sponsored company for example has 6 editors on the same view with 50k records over over 6 columns and ths occupies 0.5Mb . Note that the sessionStorage is not persistent and dies when the browser is closed so data synchronization is done once when the browser opens.
Possible future improvements:
- Live datasource synchronization instead of restarting the browser.
- Earlier datasource transmission e.g. on XafApplication.SetupCompleted event.
- Support for creating new objects.
- Any other need you may have.
Let me know if you want me to implement them for you.
Next is a screencast of a ListView cascade where as you see there are no callbacks
and the cascade/synchronization is done on the client.
-
First you need the nuget package so issue this command to the
VS Nuget package console
Install-Package Xpand.XAF.Modules.LookupCascade
.The above only references the dependencies and next steps are mandatory.
-
Ways to Register a Module or simply add the next call to your module constructor
RequiredModuleTypes.Add(typeof(Xpand.XAF.Modules.LookupCascadeModule));
The module is not bound to DevExpress versioning, which means you can use the latest version with your old DevExpress projects Read more.
The module follows the Nuget Version Basics.
.NetFramework: net461
DevExpress.ExpressApp | Any |
DevExpress.ExpressApp.Web | Any |
Fasterflect.Xpand | 2.0.7 |
JetBrains.Annotations | 2020.1.0 |
Newtonsoft.Json | 12.0.3 |
System.Reactive | 4.4.1 |
System.ValueTuple | 4.5.0 |
Xpand.Extensions | 2.202.57 |
Xpand.Extensions.Reactive | 2.202.58 |
Xpand.Extensions.XAF | 2.202.58 |
Xpand.Patcher | 2.0.24 |
Xpand.XAF.Modules.Reactive | 2.202.58 |
Xpand.VersionConverter | 2.202.10 |
To Step in the source code
you need to enable Source Server support
in your Visual Studio/Tools/Options/Debugging/Enable Source Server Support. See also How to boost your DevExpress Debugging Experience.
If the package is installed in a way that you do not have access to uninstall it, then you can unload
it with the next call at the constructor of your module.
Xpand.XAF.Modules.Reactive.ReactiveModuleBase.Unload(typeof(Xpand.XAF.Modules.LookupCascade.LookupCascadeModule))
The module is tested on Azure for each build with these tests. All Tests run as per our Compatibility Matrix