【问题标题】:UI Doesn't Hold Checkbox Value Of Selected Item In BlazorUI 不保留 Blazor 中所选项目的复选框值
【发布时间】:2023-03-14 05:50:01
【问题描述】:

我有一个 MatBlazor 表,它有一个数据源(项目)和与表中每一行关联的复选框。如果我使用@bind-Value,我没有任何问题,一切都按设计工作。但我正在向一个按钮添加验证,该验证取决于列表中的任何项目是否已“选中”以启用它。

因此,我转而使用 ValueChanged 属性,它是一个 EventCallback 并且没有运气使用所选值更新 UI。

我尝试调用 StateHasChanged() 甚至 InvokeAsync(),但 UI 没有更新。

  <MatTable Items="@Projects" class="mat-elevation-z5 create-build-list" PageSize="50" ShowPaging="false" FilterByColumnName="ProjectName" Striped="true">
                        <MatTableHeader>
                            <th>Name</th>
                            <th>Key</th>
                            <th>Type</th>
                            <th>Include</th>
                        </MatTableHeader>
                        <MatTableRow>
                            <td>@context.ProjectName</td>
                            <td>@context.Key</td>
                            <td>@context.ProjectType</td>
                            <td><MatCheckbox Label="Add To Build" ValueChanged="@((bool val) => CheckBoxValue(val, context))" ValueExpression="@(() => context.IsChecked)"></MatCheckbox></td>
                        </MatTableRow>
                    </MatTable>

方法如下

   void CheckBoxValue(bool e, MyProjectKey key)
{
    foreach(var p in Projects)
    {
        if(p.Key == key.Key)
        {
            p.IsChecked = true;
        }
    };
//-- I'll do more stuff here.
}

当它调用函数但不更新 UI 时,我是否遗漏了什么。

【问题讨论】:

  • 您的意思是将 context.Key 传递给方法吗?您似乎正在传递整个上下文/项目
  • 如果我将类型更改为字符串并只传递“密钥”而不传递对象,我会得到相同的结果。 @code{} 块中的模型显示它更新,但 UI 不保存选择。我还尝试添加 StateHasChanged() component.Base 方法来通知重新渲染,但视图仍然没有保存更改。很奇怪。

标签: c# blazor matblazor


【解决方案1】:

我不确定这是否是 Blazor/MatBlazor 的预期行为,但我遇到了同样的问题,我找到的唯一解决方案是首先使用“Value”而不是“ValueExpression”,因为这不是设置UI 适合我,然后直接在“ValueChanged”回调中设置“上下文”中的字段值,这会导致 UI 更新为“上下文”中设置的值。

因此,如果您将 Razor 代码更改为:-

<MatTable Items="@Projects" class="mat-elevation-z5 create-build-list" PageSize="50" ShowPaging="false" FilterByColumnName="ProjectName" Striped="true">
<MatTableHeader>
    <th>Name</th>
    <th>Key</th>
    <th>Type</th>
    <th>Include</th>
</MatTableHeader>
<MatTableRow>
    <td>@context.ProjectName</td>
    <td>@context.Key</td>
    <td>@context.ProjectType</td>
    <td><MatCheckbox Label="Add To Build" Value="@context.IsChecked" ValueChanged="@((bool val) => CheckBoxValue(val, context))"></MatCheckbox></td>
</MatTableRow>

然后把回调代码改成这样:-

void CheckBoxValue(bool val, MyProjectKey context)
{
    // This line updates the UI
    context.IsChecked = val;
    
    foreach (var p in Projects)
    {
        if (p.Key == context.Key)
        {
            p.IsChecked = true;
        }
    };
    
    // I'll do more stuff here.
}

希望这应该可行...

我遇到的另一个问题是与实体框架有关,因此您可能会也可能不会遇到与我相同的问题,具体取决于您在回调中执行的其他操作。

无论好坏,我在我的 ValueChanged 回调中调用了数据库插入/更新。问题在于,实体框架正在“跟踪”表列表中的所有模型,并且更新 Blazor“上下文”(不是 DbContext)也在修改被跟踪的实体!

但是,由于它只是用于显示表格行/列的模型列表,因此我在 DbContext 调用中添加了“AsNoTracking”。如果我不这样做,我会在下次我在任何地方调用“SaveChanges”时遇到有关 EF 尝试保存值的错误(有问题的 DbSet 只是链接到数据库中的一个视图,显然是只读的)! ;-)

编辑

抱歉,忘记提及这是在 Blazor 服务器项目上,因此如果您使用 Blazor 客户端项目,EF 跟踪可能不会影响您...

【讨论】:

    猜你喜欢
    • 2017-01-27
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2011-12-26
    相关资源
    最近更新 更多