数据绑定似乎已损坏

问题描述 投票:0回答:1

我正在开发一个布局设计器,想到了用于 Web 组件的 WinForms Designer,并且正处于该项目的最开始阶段。我使用 Blazor Server App,并且由于我需要一般生成控件,所以我使用 DynamicComponents。由于我不希望实际布局组件过于复杂,因此我有一个基类来处理最常见的事情。此外,我创建了一个 Selectable 节点来允许检测组件选择,而无需在每个组件中实现它。

现在选择组件时,我看到删除图标未启用,但代码已正确设置其禁用/启用状态。

但是,我可以调用 StateHasChanged ,这将显示正确的状态,但不幸的是会导致其他问题,很可能与正在使用的 DynamicComponents 有关。

我能够通过一个非常简单的示例重现我的问题,可以在这里找到: https://try.mudblazor.com/snippet/QYcIuybXTEvcExgs

我也会尝试在这里概述代码:

@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}");
    }
}

这是主要组成部分。它生成一个 Container 实例,该实例又将为所有子级提供 CascadingValue。它还注册 SelectionChanged 事件,并在选择某些内容时增加计数器(= 启用/禁用我的删除按钮)

<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();
    }
}

容器实施。如前所述,它提供了 CascadingValue 和公共方法,以便能够收到有关新选择的通知。

<div @onclick="Select">
    @ChildContent
</div>

@code {
    [CascadingParameter]
    public Container Container { get; set; }
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    private void Select()
    {
        Container.Select();
    }
}

可选择的实现。当单击某些内容时,就会调用 Container.Select() 方法。

@page "/"

<PageTitle>Index</PageTitle>

<Selectable>
    <h1>Click me to select</h1>
</Selectable>

最后,MainLayout 的主体 - 它仅包含一个可选择的文本。

如果单击“单击我进行选择”,我希望主布局上的计数器会增加,但不幸的是,只有当主布局的事件处理程序也调用 StateHasChanged 时才会发生这种情况。

我不太确定问题出在哪里,但我知道,这种绑定通常应该有效。

提前感谢您的帮助和建议!

c# html blazor
1个回答
0
投票

这是您可以做出的一项可能的改变 - 还有其他方法。

创建一个

CounterDisplay
组件:

@counter
@code {
    int counter = 0;

    public void Increment() 
    {
        counter++;
        StateHasChanged();
    }
}

将此组件添加到您的布局中:

<CounterDisplay @ref=counter />

@ref

声明本地

CounterDisplay counter;

并更改您的处理程序:

private void OnSelectionChanged()
{
    counter?.Increment();
}

现在 CounterDisplay 负责自己的

counter
并且可以在调用
Increment

时调用 StateHasChanged 来独立更新自己

在这里尝试一下

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.