【问题标题】:How to bind to element from collection/list in Blazor?如何绑定到 Blazor 中集合/列表中的元素?
【发布时间】:2020-06-10 10:48:20
【问题描述】:

我想在循环中将值绑定到列表中的元素,但我找不到好的解决方案。

<EditForm Model="@dailyReport" OnValidSubmit="@SubmitDailyReport">
        <p>
            <label>Count: </label>
            <InputNumber min="1" id="numberOfEffects" @bind-Value="numberOfEffects" />
        </p>
        @{
            for (int i = 1; i <= numberOfEffects; i++)
            {
                if (effects.Count < i)
                {
                    effects.Add("");
                }

                if (effects.Count > i)
                {
                    effects.RemoveAt(effects.Count - 1);
                }

                string concatId = "effect" + i.ToString();

                <p>
                    <label for="@concatId">@i</label>
                    <InputText id="@concatId" @bind-Value="effects.ElementAt(i-1)" />
                </p>
            }
         }
//rest code
 </EditForm>

当我尝试将值绑定到列表中的元素时,出现错误:

  1. 错误 CS0131:分配的左侧必须是 变量、属性或索引器错误
  2. 错误 CS1662:无法转换 lambda 表达式到预期的委托类型,因为一些返回 块中的类型不能隐式转换为委托 返回类型

我想知道是否有任何可能的方法将数据绑定到集合。我需要它,因为我的模型具有 List 类型的属性。在我的输入表单中,我希望允许添加用户需要的任意数量的字符串。

编辑:

@code
{
    private DailyReport dailyReport = new DailyReport();
    private List<string> effects = new List<string>();
}

我也尝试在 foreach 循环中执行此操作,但显示了另一个错误: 无法分配给“效果”,因为它是“foreach 迭代变量”

foreach (var effect in effects)
            {
                index++;
                Console.WriteLine(index);

                string concatId = "effect" + index.ToString();

                <p>
                    <label for="@concatId">@index</label>
                    <InputText id="@concatId" @bind-Value="effect" />
                </p>
            }

【问题讨论】:

标签: c# html razor blazor asp.net-core-3.0


【解决方案1】:

绑定不起作用:当输入文本的值发生变化时,您想修改列表,而不是元素本身。

相反,您必须“拆分”绑定在两个方向上的作用:

  • 根据模型的值设置输入字段的值
  • 在输入字段值变化时设置模型

下面的代码显示了如何解决主要问题,然后您必须根据需要对其进行调整。

@foreach (var element in effects.Select((e, i) => new { Effect = e, Index = i}))
{
    <p>
        <label for="@($"effect{element.Index}")">@element.Index</label>
        <input id="@($"effect{element.Index}")" value="@element.Effect"
               @onchange="@(e => effects[element.Index] = e.Value.ToString())" />
    </p>
}

@code {

    private List<string> effects = new List<string>() { "a", "b", "c" };

}

第一行起到了作用:它将列表转换为可枚举,其中每个元素都是一个新对象,它封装了effects 列表中的索引和值。您需要索引主要是因为@onchange 事件,它必须知道应该在原始列表中的哪个位置更新值。

如果您愿意,可以使用 for 循环:

@for (int i = 0; i < effects.Count; i++)
{
    // see https://stackoverflow.com/a/56426146/323447
    var iCopy = i;

    <p>
        <label for="@($"effect{i}")">@i</label>
        <input id="@($"effect{i}")" value="@effects[i]"
               @onchange="@(e => effects[iCopy] = e.Value.ToString())" />
    </p>
}

@code {

    private List<string> effects = new List<string>() { "a", "b", "c" };

}

【讨论】:

  • 我已经尝试过了,效果很好。但是在我的 onchange 函数上,我进行了一些验证,如果它是真的,那么我正在更新列表中的数据。但是当验证为假时,UI 中的值也不会重置为原始值。它仍然显示编辑后的值。尝试给 StateHasChange() 但它不起作用。
  • @Ameerudheen.K 我建议使用显示您的问题的最小代码示例发布一个新问题
  • 我已经解决了这个问题。这是我的问题链接stackoverflow.com/questions/68901935/…
猜你喜欢
  • 2020-12-06
  • 1970-01-01
  • 2014-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 2020-02-18
相关资源
最近更新 更多