如何确保 Blazor 渲染器识别集合更改
How to ensure the Blazor renderer recognises a collection change
作为内容管理页面的一部分,我有一个图像库编辑器,它显示图像列表并允许用户添加和删除图像。这是 Blazor 服务器端。
有一个连接到 ImageUpload 函数的 InputFile 按钮,它在更新后重新获取图像列表。该列表绑定到 List<ImageItemViewModel> ImageList
,只是 div 中的 @foreach
。 ImageUpload 函数完成后,它向服务器 API 询问当前图像列表并执行:
ImageList.Clear()
- ...通过API获取图像并进行一些处理,从而产生一些视图模型...
ImageList.AddRange(...image view models...)
现在,第 1 步从视觉上清除了列表 - 您得到一个空列表。 (事后看来,我承认这是我无论如何都不想做的事情)
但是第 3 步不会导致 UI 更新。
为了解决这个问题,我所做的是定义一个局部变量 tempList,它最初是空的,在步骤 2 中填充它,然后我将 ImageList 设置为 tempList。这是我一开始就应该做的,因为我现在看到如果 AddRange 起作用,Clear() 方法会导致短暂的闪烁。
但是,如果我想要这种行为,Blazor 服务器端中存在什么正确模式或什么机制可以在集合或列表更改时更新 UI?我们应该在这里使用 Observables,还是有一些可用的命令,如 NoticeUpdate(ref var) 或其他东西?
我猜,但您可能正在使用 return 为空的 Blazor 事件处理程序方法(或者有一个执行类似操作的子方法)。您的图像处理代码几乎肯定会运行异步代码。在第一次收益时,控制权被交还。没有任务等待它运行完成,运行 StateHasChanged。至此列表就清楚了。
更新
从评论来看,您似乎在代码路径中有一个不等待的异步方法。同样的结果。处理程序可能 return 一个任务,但在代码路径中有一个“未等待”的异步任务,首先让出,父代码块 运行 完成,Tasks
完成和事件处理程序完成。
Blazor 事件处理程序代码如下所示:
var task = InvokeAsync(EventMethod);
StateHasChanged();
if (!task.IsCompleted)
{
await task;
StateHasChanged();
}
如果EventMethod
只包含同步代码,它运行到完成并且StateHasChanged
被调用一次。如果 EventMethod
return 是一个 运行 任务,它会在第一次生成时调用 StateHasChanged
,然后在完成时调用。
作为内容管理页面的一部分,我有一个图像库编辑器,它显示图像列表并允许用户添加和删除图像。这是 Blazor 服务器端。
有一个连接到 ImageUpload 函数的 InputFile 按钮,它在更新后重新获取图像列表。该列表绑定到 List<ImageItemViewModel> ImageList
,只是 div 中的 @foreach
。 ImageUpload 函数完成后,它向服务器 API 询问当前图像列表并执行:
ImageList.Clear()
- ...通过API获取图像并进行一些处理,从而产生一些视图模型...
ImageList.AddRange(...image view models...)
现在,第 1 步从视觉上清除了列表 - 您得到一个空列表。 (事后看来,我承认这是我无论如何都不想做的事情) 但是第 3 步不会导致 UI 更新。
为了解决这个问题,我所做的是定义一个局部变量 tempList,它最初是空的,在步骤 2 中填充它,然后我将 ImageList 设置为 tempList。这是我一开始就应该做的,因为我现在看到如果 AddRange 起作用,Clear() 方法会导致短暂的闪烁。
但是,如果我想要这种行为,Blazor 服务器端中存在什么正确模式或什么机制可以在集合或列表更改时更新 UI?我们应该在这里使用 Observables,还是有一些可用的命令,如 NoticeUpdate(ref var) 或其他东西?
我猜,但您可能正在使用 return 为空的 Blazor 事件处理程序方法(或者有一个执行类似操作的子方法)。您的图像处理代码几乎肯定会运行异步代码。在第一次收益时,控制权被交还。没有任务等待它运行完成,运行 StateHasChanged。至此列表就清楚了。
更新
从评论来看,您似乎在代码路径中有一个不等待的异步方法。同样的结果。处理程序可能 return 一个任务,但在代码路径中有一个“未等待”的异步任务,首先让出,父代码块 运行 完成,Tasks
完成和事件处理程序完成。
Blazor 事件处理程序代码如下所示:
var task = InvokeAsync(EventMethod);
StateHasChanged();
if (!task.IsCompleted)
{
await task;
StateHasChanged();
}
如果EventMethod
只包含同步代码,它运行到完成并且StateHasChanged
被调用一次。如果 EventMethod
return 是一个 运行 任务,它会在第一次生成时调用 StateHasChanged
,然后在完成时调用。