Blazor InputCheckBox绑定Dictionary<string, bool>遇只读问题求助
问题原因
你遇到的核心问题是:Dictionary<TKey,TValue>枚举返回的KeyValuePair<TKey,TValue>是值类型(结构体),它的Value属性仅包含get访问器,是只读的。而Blazor的@bind-Value双向绑定要求绑定目标必须是可读写的属性,因此直接绑定item.Value会出现只读限制。
解决方案
下面提供两种可行的修复方案:
方案1:直接通过字典索引器绑定
利用字典的索引器(headers.Headers[item.Key])是可读写的特性,替换原来的item.Value绑定目标:
修改Razor页面的循环代码:
@foreach (var item in headers.Headers) { <tr class="row "> @if (item.Key is not null) { <td scope="col" class="col border border-1 border-secondary"> <InputCheckbox class="btn-check" @bind-Value="headers.Headers[item.Key]"> @item.Key </InputCheckbox> </td> } </tr> }
同时需要修复CsvContent构造函数中Headers未初始化的问题,否则会触发空引用异常:
public CsvContent() { Headers = new Dictionary<string, bool>(); // 初始化字典 if (FileContent is not null) { foreach (var item in FileContent) { if(item?.ElementAt(0) is not null) Headers.TryAdd(item.ElementAt(0), false); } } }
方案2:改用自定义类集合(推荐)
创建一个包含可读写属性的自定义类,替代KeyValuePair,更符合Blazor的数据绑定设计习惯:
1. 定义自定义类
public class HeaderSelection { public string Name { get; set; } public bool IsSelected { get; set; } public HeaderSelection(string name) { Name = name; IsSelected = false; } }
2. 修改CsvContent模型
将Headers属性从Dictionary<string, bool>?改为List<HeaderSelection>?,并初始化:
public class CsvContent { static Dictionary<int, char> divider = new() { { 0, ',' }, { 1, ';' }, { 2, '\t' } }; public static List<List<string>?> FileContent { get; set; } public List<HeaderSelection>? Headers { get; set; } public static async Task ReadCsvAsync(string path, int dividerCode = 2) { FileContent = new List<List<string>?>(); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); using (StreamReader reader = new StreamReader(path, System.Text.Encoding.GetEncoding(1251))) { string? line; while ((line = await reader.ReadLineAsync()) != null) { List<string> cells = new(); cells.AddRange(line.Split(divider[dividerCode])); FileContent.Add(cells); } } } public CsvContent() { Headers = new List<HeaderSelection>(); // 初始化集合 if (FileContent is not null) { foreach (var item in FileContent) { if(item?.ElementAt(0) is string headerName) Headers.Add(new HeaderSelection(headerName)); } } } }
3. 更新Razor页面的绑定代码
@foreach (var header in headers.Headers) { <tr class="row "> <td scope="col" class="col border border-1 border-secondary"> <InputCheckbox class="btn-check" @bind-Value="header.IsSelected"> @header.Name </InputCheckbox> </td> </tr> }
额外注意事项
- 原代码中
CsvContent构造函数未初始化Headers,会导致空引用异常,上述两种方案均已修复此问题。 - 方案2的自定义类方式更易于扩展(比如后续需要添加更多属性),也更符合Blazor组件的绑定逻辑,推荐使用。
内容的提问来源于stack exchange,提问作者Zufar
相关产品推荐
相关产品推荐

