Ticket T831079
Visible to All Users

Combo Box for Blazor - How to implement the scenario with cascading combo boxes and validation

created 5 years ago

Currently, I'm trying to make your example https://demos.devexpress.com/blazor/ComboBox#CascadingLists work with an async SelectedItemChanged handler, since I need to do async database read operations in that handler.
I.e.

C#
<DxComboBox Data="@Countries" TextFieldName="CountryName" SelectedItem="@CurrentCountry" SelectedItemChanged="@SelectedCountryChanged"> </DxComboBox> @code { List<Country> Countries = ...; Country CurrentCountry; async Task SelectedCountryChanged(Country country) { ... } }

This does not compile due to the async.
What does compile is this:

C#
<DxComboBox Data="@Countries" TextFieldName="CountryName" SelectedItem="@CurrentCountry" SelectedItemChanged="@(async e => await SelectedCountryChanged(e))"> </DxComboBox> @code { List<Country> Countries = ...; Country CurrentCountry; async Task SelectedCountryChanged(Country country) { ... } }

But unfortunately, during runtime, I get this exception:

C#
System.ArgumentNullException: Value cannot be null. (Parameter 'accessor') at Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create[TField](Expression`1 accessor) at DevExpress.Blazor.Internal.DxEditorBase`2.CreateFieldIdentifier() at DevExpress.Blazor.Internal.DxEditorBase`2.get_EditFormFieldIdentifier() at DevExpress.Blazor.Internal.DxEditorBase`2.get_EditFormFieldClass() at DevExpress.Blazor.DxComboBox`1.<BuildRenderTree>b__0_0(RenderTreeBuilder __builder2) at Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder.AddContent(Int32 sequence, RenderFragment fragment) at Microsoft.AspNetCore.Components.CascadingValue`1.Render(RenderTreeBuilder builder) at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment) at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry) at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception) at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue() at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender() at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(Int32 componentId, RenderFragment renderFragment) at Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged() at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync() at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception) at Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task) at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters) at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(Int32 componentId, ParameterView initialParameters) at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters) at Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters) at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c__11`1.<<InvokeAsync>b__11_0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.ViewFeatures.RazorComponents.StaticComponentRenderer.PrerenderComponentAsync(ParameterView parameters, HttpContext httpContext, Type componentType) at Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperComponentExtensions.PrerenderedServerComponentAsync(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection) at Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperComponentExtensions.RenderComponentAsync[TComponent](IHtmlHelper htmlHelper, RenderMode renderMode, Object parameters) at ZetaHelpdesk.MainBlazor.Pages.Pages__Host.<ExecuteAsync>b__10_1() in C:\p\ZetaHelpdesk\Source\Core\MainBlazor\Pages\_Host.cshtml:line 19 at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.SetOutputContentAsync() at ZetaHelpdesk.MainBlazor.Pages.Pages__Host.ExecuteAsync() at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context) at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts) at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context) at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

My question:
How can I use an async SelectedItemChanged handler in DXComboBox?

Show previous comments (1)

    Thanks, Vova, both of your assumptions are true:

    - I do place them inside an EditForm
    - I do bind them to some fields of my model object

    Hopefully, I'm just doing something wrong and you component is capable of allowing async event handlers.

    Vova (DevExpress Support) 5 years ago

      Uwe, if you place them into the EditForm component, I assume that they should be validated. Am I right?

        Validation is not my primary goal. If I cannot have built-in validation and have async event handlers instead, I would still be satisfied.

        Answers approved by DevExpress Support

        created 5 years ago (modified 5 years ago)

        Uwe, as I mentioned, the "System.ArgumentNullException: Value cannot be null. (Parameter 'accessor')" exception occurs if you place some component into Blazor's built-in EditForm component and doesn't bind this component to a model field with the two-way binding approach. So, it's necessary to bind your ComboBox with the two-way binding approach.

        However, if you use the @bind-SelectedItem construction, it's not possible to handle the SelectedItemChanged event. In your case, I recommend you define the SelectedItemExpression property. I attached a sample project illustrating this approach.
        Let me know if you have any further questions.

        Regards,
        Vova

          Show previous comments (1)
          Vova (DevExpress Support) 5 years ago

            You are welcome, Uwe!

              Today, I came accross the above "System.ArgumentNullException" again in a similar scenario.

              Could you please enhance your error checking/validation to throw a more meaningful exception like

              "It seems that you use the DevExpress XYZ Blazor compo nent within an EditForm but without binding to a model, this is currently not supported, please use the SelectedItemExpression as a workaround or bind the component to a model property"

              This would have saved me some time.

              DevExpress Support Team 5 years ago

                Hello Uwe,

                Thank you for your feedback. We have plans to change this error message and add information about it to our documentation in the future. Currently, we described this case in the Troubleshooting section that refers to the ComboBox for Blazor - How to resolve the 'System.ArgumentNullException: Value cannot be null. (Parameter 'accessor')' error ticket where a solution is given.

                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.