The binding cannot work: when the value of an input text changes, you want to modify the list, not the element itself.
Instead, you have to "split" what the binding does in the two directions:
- set the value of the input field based on the value of the model
- set the model when the value of the input field changes
The code below shows how to solve the main problem, then you have to adapt it to your needs.
@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" };
}
The first line does the trick: it converts the list to an enumerable in which each element is a new object that encapsulates both the index in the effects
list and the value. You need the index mainly because of the @onchange
event, which must know where in the original list the value should be updated.
If you prefer you can use a for loop:
@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" };
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…