C#使用Linq to JSON实现点击按钮获取上下条contentid的方法
解决方案
首先排查已知问题
- 字段
_step加了readonly修饰符,运行时无法修改值,会直接编译报错,需要先去掉readonly - 原有逻辑按
Step维度跳转,但需求是按contentid对应的单条Content维度跳转,粒度不匹配 - 下一步按钮的索引判断逻辑写反,会导致跳转逻辑异常
- 你的JSON数据存在拼写错误:第4个step的key写的是
contens,少了一个t,反序列化时该Step的Contents属性会为null,需要先修正JSON字段为contents - 原有代码中
protocol字段没有赋值逻辑,会触发空引用异常
实现思路
不用复杂的Linq查询,提前把所有Content条目按contentid的顺序拉平为一维列表,记录当前显示内容的索引,点击按钮时直接操作索引即可实现上下跳转,性能更高逻辑更清晰。
调整后完整代码
// 去掉原有readonly修饰符,新增全局字段 private Content _currentContent; private Protocol _protocol; private List<Content> _allOrderedContents; private int _currentIndex; // 构造函数需要传入完整的protocol对象 public StepView(Step step, string nextTitle, Protocol protocol) { InitializeComponent(); Title = nextTitle; _protocol = protocol; // 用Linq拉平所有Content,按contentid升序排列 _allOrderedContents = _protocol.Steps .Where(s => s.Contents != null) // 过滤掉Contents为空的异常Step .SelectMany(s => s.Contents) // 把所有Step下的Content合并成一个一维列表 .OrderBy(c => int.Parse(c.Contentid)) // 按contentid数值排序,保证顺序正确 .ToList(); // 初始化当前索引:找到传入step对应的第一个Content的位置 var initContent = step.Contents.FirstOrDefault(x => x.Text != null); _currentIndex = _allOrderedContents.FindIndex(c => c.Contentid == initContent.Contentid); if (_currentIndex < 0) _currentIndex = 0; // 找不到匹配内容时默认取第一条 // 初始化label文本 UpdateLabelText(); } public void BtnNext_Clicked(object sender, EventArgs e) { // 已经是最后一条就不跳转,也可以根据需求加提示 if (_currentIndex >= _allOrderedContents.Count - 1) return; _currentIndex++; UpdateLabelText(); } public void BtnBack_Clicked(object sender, EventArgs e) { // 已经是第一条就不跳转,也可以根据需求加提示 if (_currentIndex <= 0) return; _currentIndex--; UpdateLabelText(); } // 抽离公共的更新文本方法,减少重复代码 private void UpdateLabelText() { _currentContent = _allOrderedContents[_currentIndex]; lblText.Text = _currentContent?.Text ?? "暂无内容"; }
逻辑说明
- 拉平列表用的Linq方法
SelectMany可以把嵌套的List<Content>结构展开为一维列表,不用自己写嵌套循环 - 提前排序后直接操作索引,不用每次点击都遍历所有内容查询上一条/下一条,性能更好
- 边界情况已经处理:到第一条时点返回无响应,到最后一条时点下一步无响应,不会触发索引越界异常
内容的提问来源于stack exchange,提问作者Teun
相关产品推荐
相关产品推荐

