在 c# 中使用 linq 按钮无法从 json 中正确计算章节 ID

Posted

技术标签:

【中文标题】在 c# 中使用 linq 按钮无法从 json 中正确计算章节 ID【英文标题】:Buttons don't count chapter ids correctly from json using linq in c# 【发布时间】:2021-12-23 04:42:50 【问题描述】:

我有一个程序,用户必须根据列表视图项(章节)在协议中单击的章节从 json 获取文本

当用户没有选择协议中的第一章时单击下一步按钮时会出现问题。他总是能看到属于第一章的ID 2! 如何让它点击用户看到具有以下 id 的文本的任何章节?

我遇到的下一个问题是当我在最后一章时,我点击返回然后我进入另一章System.NullReferenceException: 'Object reference not set to an instance of an object.'继续string nextTitile = _protocol.Name + " - " + content.NavTitle;

我该如何解决这个问题?

用户在此处选择协议中的所选章节

    //for chosen step inside protocol

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

这是用户获取与所选章节关联的文本的 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": [
        
          "chapterTitle": "Voorzorg",
          "contentid": "1",
          "navTitle": "Voorzorg",
          "text": "voor blabla"
        ,
        
          "contentid": "2",
          "navTitle": "Voorzorg",
          "text": "voor blabla2"
        ,
        
          "contentid": "3",
          "navTitle": "Voorzorg",
          "text": "voor blablabla3"
        ,
        
          "contentid": "4",
          "chapterTitle": "Handeling",
          "navTitle": "Handeling",
          "text": "Handeling blabla"
        ,
        
          "contentid": "5",
          "navTitle": "Handeling",
          "text": "Handeling blabla2"
        ,
        
          "contentid": "6",
          "navTitle": "Handeling",
          "text": "Handeling blybli3"
        ,
        
          "contentid": "7",
          "chapterTitle": "Nazorg",
          "navTitle": "Nazorg",
          "text": "Nazorg blabla"
        ,
        
          "contentid": "8",
          "navTitle": "Nazorg",
          "text": "Nazorg blabla2"
        ,
        
          "contentid": "9",
          "navTitle": "Nazorg",
          "text": "Nazorg blybli3"
        
      ]
    
  ]

这是我的域类

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; 

如何解决我的问题

【问题讨论】:

【参考方案1】:

我认为这两个问题都与未在 StepView 构造函数中设置 index 属性有关。如果没有显式值,新的StepView 实例将其index 属性设置为default(int),即0

单击“下一步”按钮始终显示第二步,因为BtnNext_Clicked 递增index(到1,因为它是0),然后在该索引处显示项目。

同样,BtnBack_Clicked 递减index(到-1,因为它是0),这意味着调用_protocol.Contents.ElementAtOrDefault(index) 将返回null - 后来导致getNewNavTitle 中的NullReferenceException

您需要更新StepView 构造函数,以便正确设置index 的初始值:

public StepView(Protocol protocol, string title, string chapterTitle, int stepIndex)

    _protocol = protocol;
    InitializeComponent();
    Title = title + " - " + chapterTitle;
    // get label text
    lblText.Text = protocol.Contents.FirstOrDefault(x => x.ChapterTitle == chapterTitle).Text;

    // Set the "index" property here. You need to make sure that the "stepIndex"
    // constructor parameter has the appropriate value.
    index = stepIndex;

【讨论】:

在 StepView 构造函数中,将 index 设置为正确的值。您可能需要添加另一个参数,以便可以传入正确的值,例如:public StepView(Protocol protocol, string title, string chapterTitle, int currentIndex) index = currentIndex; @Teun 查看更新。这就是我能提供的“完整”示例。 那么我的按钮的 next 和 back 怎么样? @甜甜圈 我还需要在点击的句柄中调用 stepIndex 我应该怎么做呢? 这是你需要弄清楚的事情。您需要根据 tappedStep 确定合适的 stepIndex 值。

以上是关于在 c# 中使用 linq 按钮无法从 json 中正确计算章节 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中使用 Linq to JSON 在单击按钮时检索下一个和上一个 id

C# 无法访问 Newtonsoft.Json.Linq.JProperty 上的子值

.NET(C#) Json.Net(newtonsoft)使用LINQ查询JSON数据

如何通过按钮单击将数据导出到 linq c# 中的 .csv 文件

使用动态 LINQ 按一个或多个属性对 JSON 进行排序

使用啥代替 FirstOrDefault 来获取与 C# 中使用 linq 中所选章节关联的 json 文本?