【问题标题】:Component is not re-rendered after invoke StateHasChanged调用 StateHasChanged 后不会重新渲染组件
【发布时间】:2020-03-01 13:37:49
【问题描述】:

我已阅读文章“3 Ways to Communicate Between Components in Blazor”并尝试这样做。 我在@body 下有消息组件,并且必须根据@body 组件中的用户操作更改消息

@inject ClientMessage clientMessage
@inherits LayoutComponentBase
@using Site.Shared.Components

<div class="sidebar">
<AdminMenu />
</div>

<div class="main">
    <div class="content px-4">
        @Body
    </div>
   <Message/>
</div>

@code
{
    protected async Task ChangeState()
    {
        await InvokeAsync(StateHasChanged);
    }

    protected override void OnInitialized()
    {
        clientMessage.MsgChange += ChangeState;
    }
 }

消息组件:

@inject ClientMessage clientMessage
<div style="@(IsVisble ? "display:block" : "display:none")" class="@MsgClass" role="alert">
    @if (clientMessage != null)
    {
        @clientMessage.Message
    }
</div>

@code {

    public bool IsVisble
    {
        get
        {
            if (string.IsNullOrEmpty(@clientMessage.Message))
            {
                return false;
            }

            return true;
        }
    }

    public string MsgClass
    {
        get
        {
            if (clientMessage == null)
            {
                return string.Empty;
            }

            string msgClass;

            switch (clientMessage.MsgType)
            {
                case EMsgType.Info:
                    msgClass = "alert alert-info";
                    break;
                case EMsgType.Success:
                    msgClass = "alert alert-success";
                    break;
                case EMsgType.Warning:
                    msgClass = "alert alert-warning";
                    break;
                case EMsgType.Error:
                    msgClass = "alert alert-danger";
                    break;
                case EMsgType.NoMsg:
                default:
                    msgClass = string.Empty;
                    break;
            }

            return msgClass;
        }
    }
}

消息类

public class ClientMessage
{
    public event Func<Task> MsgChange;

    public ClientMessage(string msg, EMsgType msgType)
    {
        this.Message = msg;
        this.MsgType = msgType;
        NotifyStateChanged();
    }

    public void SetMsg(string msg, EMsgType msgType)
    {
        this.Message = msg;
        this.MsgType = msgType;
        NotifyStateChanged();
    }

    public string Message { get; set; }

    public EMsgType MsgType { get; set; }

    private void NotifyStateChanged()
    {
        if (MsgChange != null)
        {
            MsgChange.Invoke();
        }
    }
}

ClientMessage 类由 DI 作为单例注入。如果我在 @body 组件中调用 SetMsg(newMsgm, msgType) 则调用 ChangeState() 方法但没有发生任何事情,我的意思是组件没有重新渲染。如果我改为“InvokeAsync”使用“Invoke”,则会出现错误“当前线程未与 Dispatcher 关联。在触发渲染或组件状态时,使用 InvokeAsync() 将执行切换到 Dispatcher。”。如果我重新加载页面,我可以看到消息。

我做错了什么以及如何强制重新渲染消息组件?

【问题讨论】:

  • 您的消息组件没有参数,因此 Blazor 将假定它是静态的。如果您将 MainLayout 的 code 部分移动到 Message 组件,那么只要消息发生更改,它就会重新呈现自己。您还应该实现 IDisposable - 这样您就可以取消订阅 MsgChange 事件 - 以确保完整性。

标签: c# asp.net-core .net-core blazor


【解决方案1】:

我解决了这个问题。也许它会帮助某人。

我对问题进行了本地化 - 在调用 NavigationManager.NavigateTo("some_page") 后更改 @body 时,StateHasChanged() 不会重新呈现消息组件。我尝试了可以​​触发 StateHasChanged() 的不同地方,如果我将它移到 Message.razor 它会按预期工作。

比文章是better to read the documentation at the beggining:)

【讨论】:

  • 文档值得。
猜你喜欢
  • 2020-03-14
  • 2019-12-23
  • 1970-01-01
  • 2021-07-06
  • 2019-01-24
  • 2020-02-13
  • 2019-03-05
  • 2019-06-17
  • 1970-01-01
相关资源
最近更新 更多