You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# LINQ查询中替代FirstOrDefault获取对应章节JSON文本的方法

功能故障问题描述

我开发的程序需要实现如下功能:用户点击ListView内协议对应的章节条目时,从JSON数据中拉取该选中章节的关联文本,目前功能运行异常,特此寻求解决方案。

选中章节的触发代码

//for chosen step inside protocol
public void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{
    //change title based on clicked step
    var tappedStep = (Content)MyListView.SelectedItem;
    var nextTitle = Title + " - " + tappedStep.ChapterTitle;
    Navigation.PushAsync(new StepView(_protocol, Title, tappedStep.ChapterTitle));
    //Deselect item
    ((ListView)sender).SelectedItem = null;
}

故障表现

StepView页面的标签文本始终返回首个章节的第一条文本,经排查是StepView.cs中使用了FirstOrDefault查询导致的,需要调整逻辑来获取选中章节的对应文本,而非协议内的第一条文本。

StepView页面核心代码

public partial class StepView : ContentPage
{
    //get step
    private Protocol _protocol;

    //go to selected step
    public StepView(Protocol protocol, string title, string chapterTitle)
    {
        _protocol = protocol;
        InitializeComponent();
        Title = title + " - " + chapterTitle;
        // get label text
        lblText.Text = protocol.Contents.FirstOrDefault(x => x.ChapterTitle == chapterTitle).Text;
    }

    private int index;

    public void BtnBack_Clicked(object sender, EventArgs e)
    {
        index--;
        var firstId = _protocol.Contents.FirstOrDefault(x => x.Contentid != null).Contentid;
        BtnNext.IsEnabled = true;
        if (index == firstId - 1)
        {
            BtnBack.IsEnabled = false;
        }
        var content = _protocol.Contents.ElementAtOrDefault(index);
        lblText.Text = content?.Text;
        //get current navTitle on button click
        getNewNavTitle(content);
    }

    public void BtnNext_Clicked(object sender, EventArgs e)
    {
        index++;
        BtnBack.IsEnabled = true;
        if (index == _protocol.Contents.Count - 1)
        {
            BtnNext.IsEnabled = false;
        }
        var content = _protocol.Contents.ElementAtOrDefault(index);
        lblText.Text = content?.Text;
        //get current navTitle on button click
        getNewNavTitle(content);
    }

    //get new protocol + chapter based on btnBack and btnNext
    private void getNewNavTitle(Content content)
    {
        Title = null;
        string nextTitile = _protocol.Name + " - " + content.NavTitle;
        Title = nextTitile;
    }

    //go back to home
    public void btnHome_Clicked(object sender, EventArgs e)
    {
        //go to mainpage
        Navigation.PushAsync(new MainPage());
    }
}

用到的JSON数据结构

{
  "protocols": [
    {
      "id": "1",
      "name": "Pols meten",
      "contents": [
        {
          "contentid": "1",
          "chapterTitle": "Voorzorg",
          "text": "voor blabla"
        },
        {
          "contentid": "2",
          "text": "voor blabla2"
        },
        {
          "contentid": "3",
          "text": "voor blablabla3"
        },
        {
          "contentid": "4",
          "chapterTitle": "Handeling",
          "text": "handeling text"
        }
      ]
    }
  ]
}

领域类定义

public partial class RootObject
{
    [JsonProperty("protocols")]
    public List<Protocol> Protocols { get; set; }
}

public partial class Protocol
{
    [JsonProperty("id")]
    public long Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("contents")]
    public List<Content> Contents { get; set; }
}

public partial class Content
{
    [JsonProperty("contentid")]
    public long Contentid { get; set; }

    [JsonProperty("chapterTitle", NullValueHandling = NullValueHandling.Ignore)]
    public string ChapterTitle { get; set; }

    [JsonProperty("text")]
    public string Text { get; set; }
}

核心疑问

如何调整代码,无需使用FirstOrDefault即可获取选中章节起始位置对应的文本?


解决方案

你可以通过直接传递选中内容的索引和对象的方式,完全避免FirstOrDefault查询,同时修复上下翻页的逻辑错误,调整步骤如下:

1. 修改列表点击事件的传参逻辑

无需只传递章节标题,直接把选中的Content对象和它在列表中的索引传给StepView:

public void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{
    var tappedStep = (Content)MyListView.SelectedItem;
    // 直接获取选中项在协议内容列表中的索引
    int selectedIndex = _protocol.Contents.IndexOf(tappedStep);
    Navigation.PushAsync(new StepView(_protocol, Title, tappedStep, selectedIndex));
    ((ListView)sender).SelectedItem = null;
}

2. 重写StepView的构造函数,移除FirstOrDefault查询

直接用传入的选中对象赋值文本,同时初始化全局索引保证翻页逻辑正确:

public StepView(Protocol protocol, string title, Content selectedContent, int selectedIndex)
{
    _protocol = protocol;
    InitializeComponent();
    Title = title + " - " + selectedContent.ChapterTitle;
    // 直接用传入的选中对象赋值,无需查询
    lblText.Text = selectedContent.Text;
    // 初始化全局索引,修复翻页起始位置错误
    index = selectedIndex;
    // 初始化翻页按钮状态
    BtnBack.IsEnabled = index > 0;
    BtnNext.IsEnabled = index < _protocol.Contents.Count - 1;
}

3. 修复翻页逻辑的边界判断错误

你原有代码用contentid判断边界是错误的,contentid从1开始,列表索引从0开始,直接用索引判断即可:

public void BtnBack_Clicked(object sender, EventArgs e)
{
    index--;
    BtnNext.IsEnabled = true;
    if (index == 0)
    {
        BtnBack.IsEnabled = false;
    }
    var content = _protocol.Contents.ElementAtOrDefault(index);
    lblText.Text = content?.Text;
    getNewNavTitle(content);
}

额外注意点

你现有getNewNavTitle方法中用到了content.NavTitle,但你的Content类没有定义该属性,建议修改为content.ChapterTitle避免运行报错。


内容的提问来源于stack exchange,提问作者Teun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 15:42:04