Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4837

Data Binding seems to be broken

$
0
0

I am working on a layout designer, think of WinForms Designer for Web-Components, and am at the very beginning of the project. I use Blazor Server App, and, as I need to generically generate controls, am using DynamicComponents. As I don't want too much complexity within the actual layout components, I've got a base class which takes care of most common things. Additionally, I have created a Selectable node to allow detection of component selection without the need to implement that in every component.

When a component is now selected, I see that the delete icon is not getting enabled but its disabled/enabled state is correctly set by the code.

I could, however, call StateHasChanged and that would show the correct state but unfortunately lead to other issues, most likely related to the DynamicComponents being used.

I was able to reproduce my problem with a very simple example which can be found here:https://try.mudblazor.com/snippet/QYcIuybXTEvcExgs

I will try to outline the code here as well:

@inherits LayoutComponentBase<PageTitle>BlazorRepro</PageTitle>@Counter<Container @ref="@container"><div>    @Body</div></Container>@code {    Container? container;    int Counter { get; set; }    protected override void OnAfterRender(bool firstRender)    {        base.OnAfterRender(firstRender);        if (container != null && firstRender)            container.SelectionChanged += OnSelectionChanged;    }    private void OnSelectionChanged()    {        System.Diagnostics.Trace.WriteLine($"Counter incremented to : {++Counter}");    }}

That's the main component. It generates a Container instance which, in turn, will provide a CascadingValue to all children. It also registers for the SelectionChanged event and increments a counter when ever something is selected (= Enabling/Disabling of my delete button)

<div class="container"><CascadingValue Value="this">    @ChildContent</CascadingValue></div>@code {    [Parameter]     public RenderFragment? ChildContent { get; set; }    public event Action? SelectionChanged;    public void Select()    {        SelectionChanged?.Invoke();    }}

Container implementation. As mentioned, it provides a CascadingValue and also a public method to be able to be notified about a new selection.

<div @onclick="Select">    @ChildContent</div>@code {    [CascadingParameter]    public Container Container { get; set; }    [Parameter]    public RenderFragment ChildContent { get; set; }    private void Select()    {        Container.Select();    }}

The Selectable implementation. When ever something is clicked, the Container.Select() method is invoked.

@page "/"<PageTitle>Index</PageTitle><Selectable><h1>Click me to select</h1></Selectable>

Finally, the body of the MainLayout - It just wraps a selectable text.

If 'Click me to select' is clicked, I would expect the counter on the main layout to be incremented but unfortunately, that only happens if the event handler of the main layout is also calling StateHasChanged.

I am not exactly sure where the problem comes from but I know, that that kind of binding should work in general.

Thank you in advance for your help and suggestions!


Viewing all articles
Browse latest Browse all 4837

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>