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

Posted

技术标签:

【中文标题】如何在 C# 中使用 Linq to JSON 在单击按钮时检索下一个和上一个 id【英文标题】:How to retrieve the next and previous ids on a button click using Linq to JSON in C# 【发布时间】:2021-12-21 06:50:16 【问题描述】:

在我的 json 文件的步骤中,我想构建一个 linq,它根据您是点击后退按钮(上一个 id)还是下一个按钮(下一个 contentid)移动到下一个或上一个 id。如果发生这种情况,必须修改标签的文本。我不确定如何在 Linq 中实现这一点。

这是我的 JSON,我需要基于 contentid 步骤中的下一个或上一个文本


  "protocols": [
    
      "id": "1",
      "name": "Pols meten",
      "steps": [
        
          "chapterTitle": "Voorzorg",
          "contents": [
            
              "contentid": "1",
              "text": "voor blabla"
            
          ]
        ,
        
          "contents": [
            
              "contentid": "2",
              "text": "voor blabla2"
            
          ]
        ,
        
          "chapterTitle": "Handeling",
          "contents": [
            
              "contentid": "3",
              "text": "handeling blabla"
            
          ]
        ,
        
          "contens": [
            
              "contentid": "4",
              "text": "handeling blabla2"
            
          ]
        ,
        
          "chapterTitle": "Nazorg",
          "contents": [
            
              "contentid": "5",
              "text": "nazorg blabla"
            
          ]
        ,
        
          "contents": [
            
              "contentid": "6",
              "text": "nazorg blabla2"
            
          ]
        
      ],
      "versie": "1"
    
  ]

我的 json 类

    public class RootObject
    
        [JsonProperty("protocols")]
        public List<Protocol> Protocols  get; set; 
    
    public class Protocol
    
        [JsonProperty("id")]
        public string Id  get; set; 
        [JsonProperty("name")]
        public string Name  get; set; 
        [JsonProperty("steps")]
        public List<Step> Steps  get; set; 
        [JsonProperty("versie")]
        public string Versie  get; set; 
    
    public class Step
    
        [JsonProperty("chapterTitle")]
        public string ChapterTitle  get; set; 
        [JsonProperty("contents")]
        public List<Content> Contents  get; set; 
    
    public class Content
    
        [JsonProperty("contentid")]
        public string Contentid  get; set; 
        [JsonProperty("text")]
        public string Text  get; set; 
    

坐下是我的 2 个按钮,当我点击它时,我会转到下一个或上一个 id(如果它们存在)

        readonly Step _step;
        private Protocol protocol;
    public StepView(Step step, string nextTitle)
    
        _step = step;
        InitializeComponent();
        Title = nextTitle;
        // krijg label text
        lblText.Text = step.Contents.FirstOrDefault(x => x.Text != null).Text;
    
      public void BtnNext_Clicked(object sender, EventArgs e)
    
        if (_step == null)
        
            lblText.Text = _step.Contents.FirstOrDefault(x => x.Text != null).Text;
        
        else
        
            var index = protocol.Steps.IndexOf(_step) + 1;
            _step = protocol.Steps.Count >= index ? protocol.Steps.LastOrDefault() : protocol.Steps[index];
        

        lblText.Text = _step?.Contents.FirstOrDefault(x => x.Text != null).Text;
    

    public void BtnBack_Clicked(object sender, EventArgs e)
    
        //voor als het de allerlaatste stap is en je geen stap meer terug kan 
        if (_step == null)
        
            _step = protocol.Steps.LastOrDefault();
        
        //als je nog wel een stap terug kunt 
        else
        
            var index = protocol.Steps.IndexOf(_step) - 1;
            _step = index >= 0 ? protocol.Steps[index] : protocol.Steps.FirstOrDefault();
        

        lblText.Text = _step?.Contents.FirstOrDefault(x => x.Text != null).Text;
    

如果有的话,我怎样才能让按钮在上一个文本或下一个文本之后?

【问题讨论】:

BtnClicked = true; if (BtnClicked) .... 该代码的用途是什么?如果您想跟踪当前步骤,您至少需要从 _step 中删除 readonly 并在使用索引计算单击按钮时更改它。 你能举个例子吗? @AlexeyRumyantsev 这个布尔值没有意义,我不认为在这种情况下用户可以同时按下多个按钮来担心并发性。您应该担心正确的 null 和范围检查,而不是多线程。 【参考方案1】:

引入字段private Content content;

处理程序:

public void BtnNext_Clicked(object sender, EventArgs e)

    var index = content == null ? 0 : _step.Contents.IndexOf(content) + 1;
    content = _step.Contents.ElementAtOrDefault(index);
    lblText.Text = content?.Text;


public void BtnBack_Clicked(object sender, EventArgs e)

    var index = content == null ? _step.Contents.Count - 1 : _step.Contents.IndexOf(content) - 1;
    content = _step.Contents.ElementAtOrDefault(index);
    lblText.Text = content?.Text;

【讨论】:

我得到 System.NullReferenceException: Object reference not set to an instance of an object. var index = protocol.Steps.IndexOf(_step) - 1; 那要改什么? 协议为空 rootObject.Protocols.FirstOrDefault().Steps.ElementAtOrDefault(startingIndex -/+1) 会得到你想要的索引 你能给出一个带有@PowerMouse的代码示例【参考方案2】:

如您所愿。我做了一个例子。您传递所选项目的索引和方向以选择下一个项目,例如上一个或下一个 (您可以删除 where 条件 - 我将在此示例中查看包含标题的记录)

void Main()

    string json = "\"protocols\":[\"id\":\"1\",\"name\":\"Pols meten\",\"steps\":[\"chapterTitle\":\"Voorzorg\",\"contents\":[\"contentid\":\"1\",\"text\":\"voor blabla\"],\"contents\":[\"contentid\":\"2\",\"text\":\"voor blabla2\"],\"chapterTitle\":\"Handeling\",\"contents\":[\"contentid\":\"3\",\"text\":\"handeling blabla\"],\"contens\":[\"contentid\":\"4\",\"text\":\"handeling blabla2\"],\"chapterTitle\":\"Nazorg\",\"contents\":[\"contentid\":\"5\",\"text\":\"nazorg blabla\"],\"contents\":[\"contentid\":\"6\",\"text\":\"nazorg blabla2\"]],\"versie\":\"1\"]";
    rootObject = JsonConvert.DeserializeObject<RootObject>(json);
    
    rootObject.Dump();

    GetPrevNextItem(1,Direction.Up).Dump("Previous record");
    GetPrevNextItem(1,Direction.Down).Dump("Next Record");
    


public Step GetPrevNextItem(int startingIndex, Direction dir)

    if (dir == Direction.Up)
    return rootObject.Protocols.FirstOrDefault().Steps
                    .Where(ss=> !string.IsNullOrEmpty(ss.ChapterTitle))
                    .ElementAtOrDefault(startingIndex -1);
    else
    return rootObject.Protocols.FirstOrDefault().Steps
                    .Where(ss=> !string.IsNullOrEmpty(ss.ChapterTitle))
                    .ElementAtOrDefault(startingIndex +1);


public enum Direction

    Up,
    Down


public RootObject rootObject get;set;

public class RootObject

    [JsonProperty("protocols")]
    public List<Protocol> Protocols  get; set; 

public class Protocol

    [JsonProperty("id")]
    public string Id  get; set; 
    [JsonProperty("name")]
    public string Name  get; set; 
    [JsonProperty("steps")]
    public List<Step> Steps  get; set; 
    [JsonProperty("versie")]
    public string Versie  get; set; 

public class Step

    [JsonProperty("chapterTitle")]
    public string ChapterTitle  get; set; 
    [JsonProperty("contents")]
    public List<Content> Contents  get; set; 

public class Content

    [JsonProperty("contentid")]
    public string Contentid  get; set; 
    [JsonProperty("text")]
    public string Text  get; set; 


【讨论】:

以上是关于如何在 C# 中使用 Linq to JSON 在单击按钮时检索下一个和上一个 id的主要内容,如果未能解决你的问题,请参考以下文章

在JS和.NET中使用JSON (以及使用Linq to JSON定制JSON数据)

LINQ to XML:如何在 C# 中获取元素值?

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

如何在 c# 中添加特定条件项后对特定元素进行分组 linq to sql

在 C# 中使用 LINQ 方法语法 (LINQ to SQL) 时发生异常

在 C# 中使用 Linq 单击按钮时,Json 不会转到下一个或上一个文本