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

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

My full code can be found here:https://github.com/Romout/LayoutDesigner

The problem is that when adding an alpha numeric and selecting it by clicking on it, the delete icon on top is not activated which indicates, that the data binding for 'DeleteDisabled' did not work.

I will try to outline the simple example 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 4291

Latest Images

Trending Articles



Latest Images

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