【问题标题】:Blazor Server Page not refreshing after database has been successfully updated成功更新数据库后,Blazor 服务器页面未刷新
【发布时间】:2020-08-27 17:20:19
【问题描述】:

我的问题可能很简单,但我一直在反复尝试了解问题所在。我有一个带有单独模型类的 Blazor 页面(在代码中循环时引用为 LsC 的 List<Type> 或 ls 的单),用于加载数据。但是,当我单击以更新该数据时,页面不会刷新。如果我添加一个新条目,该页面会加载新条目。

Blazor 页面代码有问题很简单:

@if (ls.PrimaryContact)
{
    <div style="cursor: pointer;" class="badge badge-pill badge-success">Primary</div>
}
else
{
    <div style="cursor: pointer;" @onclick="@(() =>MakePrimaryContact(@ls.Id))" class="badge badge-pill badge-info">Make Primary</div>
}

当主要字段中的结果为真时,代码应放置一个绿色药丸,或者放置一个带有制作主要文本的常规信息药丸。手动 (F5) 刷新页面时,代码可以正常工作。但是当我单击 Make Primary 药丸时,数据库会更新,但页面不会。我必须再次手动更新页面以正确反映更改。

它调用onClick的函数:

private void MakePrimaryContact(int LCId)
{
    LeadsContactsGateway LCGw = new LeadsContactsGateway();
    var wt = LCGw.UpdatePrimary(Lead.Id, LCId);
    LsC = LsCGw.GetByLeadsId(Id);
    StateHasChanged();
    OnInitialized();
}

我添加了StateHasChanged() 作为附加措施,但我的页面没有获取具有正确主要联系人的更新记录集。直到我手动 (F5) 刷新网页时才会反映正确的更新。

奇怪的是,在同一页面上,我还有另一个按钮,用于添加新的数据库条目并自动弹出更新。

没有有问题的新数据库条目的代码:

<button class="btn btn-primary btn-sm" @onclick="() => NewLeadContactModal.Open()">+ New 
    <i class="icon icon-people-fill icon-white"></i>
</button>

...

<Modal @ref="@NewLeadContactModal">
<Title>Add New Contact for: @Lead.LeadName</Title>
<Body>
    <ContactAdd LeadsId="@Lead.Id"></ContactAdd>
</Body>
<Footer>
    <button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => ContactModalClickHandler(0)">Close</button>
</Footer>
...
 private void ContactModalClickHandler(int completed)
 {
    if (completed > 0)
    { }
    NewLeadContactModal.Close();
    OnInitialized();

 }

任何建议将不胜感激。

【问题讨论】:

  • 永远不要自己调用 OnInitialized,它是一个只有 Blazor 应该调用的生命周期方法。我认为您的问题是您的方法实际上并未更新 lsLead
  • 谢谢@peter。如果我不调用 OnInitialized,就像我在模式插入记录之后所做的那样,页面不会刷新。在模式代码上,我添加了 OnInitialized 以更新记录并显示;然而,当我在这个简单的记录更新上做同样的事情时,页面并没有反映应该在“ls”上发生的变化。
  • @Mariano 如果OnInitialized 做了一些您想在别处重复使用的工作,请将其移至单独的方法并从两者中调用该方法。 @peter 的建议很好
  • @Quango,谢谢。我将尝试只使用一种调用 OnInitialized 的方法。彼得,谢谢,我仍在努力了解 Blazor 是如何协同工作的,我绝不会取消建议的资格。

标签: c# blazor blazor-server-side


【解决方案1】:

我猜你是在 OnInitialized() 方法上调用数据库方法

您可以尝试使用 StateHasChanged() 进行相同操作吗?您可以在此处找到文档

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.componentbase.statehaschanged

否则,唯一的解决方案是更改您在 UI 中绑定的项目的值

【讨论】:

  • 感谢@Mangesh Gaherwar,我确实在使用有问题的代码调用的函数上添加了 StateHasChanged()。奇怪的是,当我在数据库中添加一条记录并关闭模式时,我只调用 onInitialized() 并且新记录会自动刷新显示在页面上。
  • OnIntialized() 重新渲染您的组件,因此它将是一个数据库调用,它将刷新组件,否则您将需要检查操作状态并相应地修改您的绑定模型
  • 奇怪的是,如果我在模式上添加记录,我不需要担心绑定。我所做的只是更新数据库中的记录。既然已经绑定了,应该反映 OnInitialized() 上的变化,还是不反映?我对你的理解正确吗?
【解决方案2】:

在您的代码中:

@if (ls.PrimaryContact)
{
    <div style="cursor: pointer;" class="badge badge-pill badge-success">Primary</div>
}
else
{
    <div style="cursor: pointer;" @onclick="@(() =>MakePrimaryContact(@ls.Id))" class="badge badge-pill badge-info">Make Primary</div>
}

在这里你写了 -ls.PrimaryContact- if -ls- is a reference type when you change this 不需要刷新页面,因为这个 blazor 正在更改页面代码

如果 -ls 或 ls.PrimaryContact- 不是引用类型,您应该在页面组件中创建一个参数,如下所示;

[Parameter] 
public YourModel YourParam { get; set; }

然后

当你调用组件时

<MyComponent YourParam ="@Data"></MyComponent>

所以它会像这样工作

我的样本包括在下面;

@foreach (var item in AllCourseMaster){
     @if(item.Active){
       <div id="first"></div>
      }
     else
     {
      <div id="second"></div>  
     }
}
<button @onclick="@(e=>CollapseClick(item.Id))"></button>

有效

@code{
   void CollapseClick(int id)
    {
        var changed=AllCourseMaster.FirstOrDefault(x=>x.Id==id);
        changed.Active= !changed.Active;
    }
}

【讨论】:

  • 非常感谢您的回复。是的 ls 是来自模型的引用类型。我没有放整个代码,因为它相当广泛。可以说 ls 来自一个循环,该循环从 'List LsC = new List();' 获取每个单独的 'ls'这里的主要问题是整个循环完美地工作。当我单击 Make Primary 药丸时,数据库确实会更改主字段,但当我调用 StateHasChanged() 或 OnInitialized() 时页面不会刷新。
  • 这个方法是事件,所以它们在事件之后起作用;在我的代码 AllCourseMaster 中,当我从中更改数据时,视图已更改;页面不刷新。如果您想重新加载,请访问此; stackoverflow.com/questions/59583410/…
  • 感谢您对另一篇文章的引用。我看到了相似之处。实际上,页面刷新 (f5) 是它实际刷新已更新数据的唯一方式。我觉得奇怪的是,Blazor 组件页面仅在将记录添加到数据库时才会自动刷新,而不会在更新时自动刷新。我还没有找到一个干净的答案。由于我使用自定义选项卡页面组件,因此此选项对我来说不是一个可行的解决方案,因为它会将页面重新加载回主体或第一个选项卡。
【解决方案3】:

非常感谢您的意见,因为它不会让我得到答案。随着我进一步研究并从您的所有答案中了解更多信息,我发现此问题的关键不仅与更新 UI 和数据库有关,而且还需要刷新 DBSet 并在记录集上重新填充数据。我在函数中添加了LsC = LsCGw.GetByLeadsId(Id); 的简单行。完整功能如下:

private async Task MakePrimaryContact(int LCId)
    {
        bool isConfirmed = await js.InvokeAsync<bool>("confirm", "Please confirm you want to make Primary?");
        if (isConfirmed)
        {
            LsCGw.UpdatePrimary(Ls.Id, LCId);
            LsC = LsCGw.GetByLeadsId(Id);
            StateHasChanged();
            OnInitialized();
        }
    }

有些人会说我需要删除 OnInitialized(),但是当我这样做时,它不能仅与 StateHasChanged() 一起使用。照原样,它确实有效。添加用于将线索返回记录集中的行实际上是刷新所有数据以正确刷新 UI。

再次感谢您。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-27
    • 2016-10-09
    • 2013-03-14
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    相关资源
    最近更新 更多