【问题标题】:Blazor - Two-way binding on a CollectionBlazor - 集合上的双向绑定
【发布时间】:2021-07-29 18:35:39
【问题描述】:

是否可以在 Blazor 子组件中双向绑定集合?

TLDR;当执行ValueChangedEventCallBack 处理程序时,对象中的列表类型属性设置为null,这会抛出NullReferenceExceptions,因为它在页面中设置为null

我有以下例子:

    public class Person
    {
        public string FullName { get; set; }
        public List<string> NickNames { get; set; } = new List<string>();
    }

首页:Index.razor


<h1>@Mario.FullName - @string.join('-', Mario.NickNames)</h1>
<NicknamesListComponent @bind-Nicknames="Mario.NickNames" />

@code{
    public Person Mario { get; set; } = 
        new Person() { FullName = "Mario", NickNames = new List<string> {"Super", "Mama" , "Mia"} }

}

子组件:NicknamesListComponent.razor


<ul>
    @for(int i = 0; i < Nicknames.Count; i++)
    {
      @var index = i;
      <li>
         @Nicknames[index]
         <a @onclick="() => RemoveNickname(index)">Remove</a>
      </li>
    }
</ul>

@code {
    [Parameter]
    public List<string> Nicknames { get; set; }

    [Parameter]
    public EventCallback<List<string>> NicknamesChanged { get; set; }

    public async Task RemoveNickname(int index)
    {
        Nicknames.RemoveAt(index);

        //////////////////////////////////////////////////////////
        // When executing NicknamesChanged. the User.Nicknames property is completly cleared and 
        // set to NULL... this throws exceptions everywhere in the index.blazor
        await NicknamesChanged.InvokeAsync();
    }
}

如果我删除了NicknamesChanged,那么带有删除按钮的列表就可以工作了...但是这次父母不会收到更改通知并且昵称保持不变...

【问题讨论】:

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


    【解决方案1】:

    null 是因为您使用 void 调用 NicknamesChanged.InvokeAsync()

    两种方式的绑定工作:

        await NicknamesChanged.InvokeAsync(Nicknames);
    

    旁注:我假设这是一个错字,但string.Join(...) 不是string.join(...)

    如果您解决了这两个问题,您的代码将可以正常工作。不过……

    避免for循环问题的更好方法:

    <ul>
        @foreach(var nickname in Nicknames)
        {
          <li @key=nickname>
             @nickname
             <a @onclick="() => RemoveNickname(nickname)">Remove</a>
          </li>
        }
    </ul>
    
    @code {
        [Parameter]
        public List<string> Nicknames { get; set; }
    
        [Parameter]
        public EventCallback<List<string>> NicknamesChanged { get; set; }
    
        public async Task RemoveNickname(string nickname)
        {
            Nicknames.Remove(nickname);
            await NicknamesChanged.InvokeAsync(Nicknames);
        }
    }
    

    应该使用@key,因为您可以删除错误的昵称。

    Repl

    【讨论】:

    • 甜蜜!是的,await NicknamesChanged.InvokeAsync(Nicknames) 成功了!不知道为什么微软没有在文档中注意到这一点,谢谢!使用 RemoveAt() 而不是 Remove() 的原因纯粹是出于性能方面的考虑,我同意这是更简洁的代码。 +1
    【解决方案2】:

    您必须在 NicknamesChanged 上返回 NickNames,建议不要更改 NickNames 参数。改用局部变量。

    更新后的代码是:

    <ul>
        @for (int i = 0; i < Nicknames.Count; i++)
        {
            var index = i;
            <li>
                @Nicknames[index]
                <a @onclick="() => RemoveNickname(index)">Remove</a>
            </li>
        }
    </ul>
    @code {
        [Parameter]
        public List<string> Nicknames { get; set; }
    
        [Parameter]
        public EventCallback<List<string>> NicknamesChanged { get; set; }
    
        public async Task RemoveNickname(int index)
        {
            Nicknames.RemoveAt(index);
    
            await NicknamesChanged.InvokeAsync(Nicknames);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-26
      • 1970-01-01
      • 2022-11-07
      • 2023-02-24
      • 2014-12-24
      • 2019-10-01
      • 2020-01-15
      • 1970-01-01
      相关资源
      最近更新 更多