Ticket T994515
Visible to All Users

Blazor - How to integrate the Pivot Grid into an XAF app

created 4 years ago

Do you have an example of creating a custom list editor for Blazor please?

I am trying to bind DxPivotGrid to a list of a simple class I defined as an example.

C#
public class ResultObject : IXafEntityObject, IObjectSpaceLink, INotifyPropertyChanged { public ResultObject() { // In the constructor, initialize collection properties, e.g.: // this.AssociatedEntities = new List<AssociatedEntityObject>(); } [Browsable(false)] // Hide the entity identifier from UI. public Int32 ID { get; protected set; } // You can use the regular Code First syntax: public string Name { get; set; } public string Name0 { get; set; } public string Name1 { get; set; } public string Name2 { get; set; } public string Name3 { get; set; } public double V1 { get; set; } public double V2 { get; set; } public double V3 { get; set; } #region IXafEntityObject members (see https://documentation.devexpress.com/eXpressAppFramework/clsDevExpressExpressAppIXafEntityObjecttopic.aspx) void IXafEntityObject.OnCreated() { // Place the entity initialization code here. // You can initialize reference properties using Object Space methods; e.g.: // this.Address = objectSpace.CreateObject<Address>(); } void IXafEntityObject.OnLoaded() { // Place the code that is executed each time the entity is loaded here. } void IXafEntityObject.OnSaving() { // Place the code that is executed each time the entity is saved here. } #endregion #region IObjectSpaceLink members (see https://documentation.devexpress.com/eXpressAppFramework/clsDevExpressExpressAppIObjectSpaceLinktopic.aspx) // Use the Object Space to access other entities from IXafEntityObject methods (see https://documentation.devexpress.com/eXpressAppFramework/CustomDocument113707.aspx). private IObjectSpace objectSpace; IObjectSpace IObjectSpaceLink.ObjectSpace { get { return objectSpace; } set { objectSpace = value; } } #endregion #region INotifyPropertyChanged members (see http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx) private void OnPropertyChanged([CallerMemberName] string propertyName = null) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; #endregion }

This is as far as I got in my attempt to create the Custom List editor:

C#
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BlazorCoreSol.Module.BusinessObjects.DataModel; using DevExpress.Blazor; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using DevExpress.ExpressApp.Utils; namespace BlazorCoreSol.Module.Blazor.Editors { [ListEditor(typeof(ResultObject))] public class BlazorResultListEditor : ListEditor { public BlazorResultListEditor(IModelListView info) : base(info) { } private DxPivotGrid<ResultObject> control; public override SelectionType SelectionType => throw new NotImplementedException(); protected override object CreateControlsCore() { control = new DxPivotGrid< ResultObject>(); return control; } protected override void AssignDataSourceToControl(Object dataSource) { DxPivotGridDataProvider<ResultObject> PivotGridDataProvider = DxPivotGridDataProvider<ResultObject>.Create<IList<ResultObject>>(ListHelper.GetList(dataSource) as IList<ResultObject>); if (control != null) { control.Data = .AsQueryable< ResultObject>(); } } public override void Refresh() { } private object focusedObject; public override object FocusedObject { get { return focusedObject; } set { focusedObject = value; } } public override IList GetSelectedObjects() { List<object> selectedObjects = new List<object>(); if (FocusedObject != null) { selectedObjects.Add(FocusedObject); } return selectedObjects; } } }

Thank you

Comments (2)
DevExpress Support Team 4 years ago

    Hi Philip,

    At present, we don't have an example of how to create a custom List Editor in XAF Blazor. We recommend using custom Razor components for this. This approach is illustrated at:

      Thank you for the references. I managed to get a little further and now have a running mini-application. Unfortunately, I cannot figure out how to assign a data source to the actual control.

      I have attached the project.

      C#
      protected override void AssignDataSourceToControl(Object dataSource) { DxPivotGridDataProvider<ResultObject> PivotGridDataProvider = DxPivotGridDataProvider<ResultObject>.Create<IList<ResultObject>>(ReturnData(dataSource)); if (control != null) { control.Data = PivotGridDataProvider.PivotGridDataSource; } }

      It would be fantastic if it were possible to figure out how to integrate the PivotGrid in XAF Blazor since this is the remaining blocker preventing us from using Blazor for our application.

      Answers approved by DevExpress Support

      created 4 years ago (modified a year ago)

      Hello Philip,

      Thank you for sharing your results. The ListEditor.CreateControlsCore method should return a class that implements the IComponentContentHolder interface. The IComponentContentHolder.ComponentContent method should create a Razor component with the required control (DxPivotGrid). Here is an example:

      Note
      We created this example only for demonstration purposes. We can't guarantee that it will work in all usage scenarios. If you need to add some functionality to it, feel free to do this on your own. Researching DevExpress source code will help you with this task. Also, refer to the following help topic for more information: Debug DevExpress .NET Source Code with Debug Symbols. Unfortunately extending this example with custom code is outside the scope of our Support Service: Technical Support Scope.

      SolutionName.Module.Blazor\Editors\XafPivotGridModel.cs

      C#
      using DevExpress.Blazor; using DevExpress.ExpressApp.Blazor; using Microsoft.AspNetCore.Components; using System; using System.Collections.Generic; namespace BlazorCoreSol.Module.Blazor.Editors { public class XafPivotGridModel<T> { public IEnumerable<T> Data { get; set; } public IEnumerable<XafPivotGridFieldModel> Fields { get; set; } public Action Update { get; set; } } public class XafPivotGridFieldModel { public string Name { get; set; } public PivotGridFieldArea Area { get; set; } } public class XafPivotGridAdapter<T> : IComponentContentHolder { XafPivotGridModel<T> model; public XafPivotGridAdapter(XafPivotGridModel<T> model) { this.model = model; } public RenderFragment ComponentContent => XafPivotGrid<T>.Create(model); } }

      SolutionName.Module.Blazor\Editors\XafPivotGrid.razor

      Razor
      @typeparam T @using DevExpress.Blazor <DxPivotGrid Data=@Model.Data> @foreach (XafPivotGridFieldModel field in Model.Fields) { <DxPivotGridField Field=@field.Name Area=@field.Area /> } </DxPivotGrid> @code { [Parameter] public XafPivotGridModel<T> Model { get; set; } public static RenderFragment Create(XafPivotGridModel<T> model) =>@<XafPivotGrid Model=@model/>; protected override void OnInitialized() { base.OnInitialized(); Model.Update = StateHasChanged; } }

      Please see additional information about implementing Razor components in Microsoft documentation: ASP.NET Core Blazor component rendering.

      In addition, it is not necessary to use the DxPivotGridDataProvider class - this class is intended only for synchronization between DxChart and DxPivotGrid. To assign a data source, you can get a ListView's Collection Source by implementing the IComplexListEditor interface in your List Editor, and use the CollectionSourceBase.GetEnumerable method to get a data source. Alternatively, process the QueryableCollection object from the List Editor's Data Source in the AssignDataSourceToControl method. Bind this data source to the aforementioned Razor component using its model (XafPivotGridModel):

      SolutionName.Module.Blazor\Editors\BlazorResultListEditor.cs

      C#
      using BlazorCoreSol.Module.BusinessObjects.DataModel; using DevExpress.Blazor; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using System; using System.Collections; using System.Collections.Generic; namespace BlazorCoreSol.Module.Blazor.Editors { [ListEditor(typeof(ResultObject))] public class BlazorResultListEditor : ListEditor { public BlazorResultListEditor(IModelListView info) : base(info) { } private XafPivotGridModel<ResultObject> pivotGridModel; protected override object CreateControlsCore() { pivotGridModel = new XafPivotGridModel<ResultObject>(); pivotGridModel.Fields = new XafPivotGridFieldModel[] { new XafPivotGridFieldModel() { Name = nameof(ResultObject.V1), Area = PivotGridFieldArea.Data }, new XafPivotGridFieldModel() { Name = nameof(ResultObject.Name), Area = PivotGridFieldArea.Row }, new XafPivotGridFieldModel() { Name = nameof(ResultObject.Name1), Area = PivotGridFieldArea.Column } }; return new XafPivotGridAdapter<ResultObject>(pivotGridModel); } protected override void AssignDataSourceToControl(Object dataSource) { if (pivotGridModel != null && dataSource is QueryableCollection queryableCollection) { pivotGridModel.Data = (IEnumerable<ResultObject>)queryableCollection.Queryable; } } protected override void OnDataSourceChanged() { base.OnDataSourceChanged(); if (pivotGridModel != null) { pivotGridModel.Update(); } } public override void Refresh() { } public override object FocusedObject { get; set; } public override IList GetSelectedObjects() { return new object[0]; } public override SelectionType SelectionType { get { return SelectionType.None; } } } }

      I have attached a complete sample project. Note that this is a simplified example that is intended to show the basic principles of creating a component and binding it to ListView data. We are not going to extend it - instead, we will implement a fully-functional Pivot Grid Module in future releases (presumably, in v21.2).

      This example creates a component with predefined settings. For a more flexible solution, extend the ListView model with various Pivot Grid settings, and configure XafPivotGridModel based on them. Please refer to the following help topic for additional information: How to: Extend the Application Model.

      If you need to implement additional operations and business logic, please feel free to use GridListEditor's source code as an example: C:\Program Files (x86)\DevExpress 21.1\Components\Sources\DevExpress.ExpressApp\DevExpress.ExpressApp.Blazor\Editors\Grid.

      To see other examples of integrating custom controls in XAF, refer to FAQ: XAF ASP.NET Core Blazor Server UI - How to use components that are not integrated in the Blazor UI by default?

      Please feel free to contact us if you need further assistance.

      See Also

      Clipboard-File-2.png

        Comments (3)

          Thanks very much Anatol. This example is fantastic. I have got the example up and running.

          A couple of questions about the component itself now:

          1. In the Aspx version, there were some properties on a field
          C#
          ( tagField.AllowedAreas = PivotGridAllowedAreas.ColumnArea | PivotGridAllowedAreas.RowArea | PivotGridAllowedAreas.FilterArea;)

          Are these properties going to reappear in future Beta releases?
          2. The old control provided a pop up menu from which one could choose fields to drop onto the RowArea, ColumnArea etc. Will that functionality be part of the new control or is it envisioned a user should program it themselves outside this control?
          3. Is it possible to use Custom Summary methods as was permitted in the old control?

          C#
          tagField.SummaryType = DevExpress.Data.PivotGrid.PivotSummaryType.Custom;

          Thanks in advance for the great support you provide.

          Anatol (DevExpress) 4 years ago

            Hello Philip,

            I appreciate your feedback. I created a separate ticket with your questions for our Blazor Components team: T995574: Pivot Grid runtume customization and custom summaries. We placed it in our processing queue and will process it shortly.

            Dennis Garavsky (DevExpress) 4 years ago

              At present, we don't have an example of how to create a custom List Editor in XAF Blazor.

              You may also find our new help topic useful for the future: How to: Use a Custom Component to Implement List Editor (Blazor).

              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.