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

Posted

技术标签:

【中文标题】使用啥代替 FirstOrDefault 来获取与 C# 中使用 linq 中所选章节关联的 json 文本?【英文标题】:What to use instead of FirstOrDefault to get the json text associated with the chosen chapter in C# using linq?使用什么代替 FirstOrDefault 来获取与 C# 中使用 linq 中所选章节关联的 json 文本? 【发布时间】:2021-12-23 00:33:42 【问题描述】:

我有一个程序,用户必须根据列表视图项(章节)在协议中单击的章节从 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;
    

接下来的问题是标签文本始终是第一章的第一个文本这是因为我在下一个类中使用 FirstOrDefault StepView.cs 这里的逻辑必须是这样的,它采用属于的文本到对应的章节!而不是协议中的第一个。

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",
    
  ]

这是我的域类

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 成为所选章节开头的文本?

【问题讨论】:

请不要用您给出的答案编辑问题。问题保持原样,如果你重写它,接受的答案对未来的读者不再有意义。如果您有后续问题,请创建一个新问题,不要编辑原始问题。 【参考方案1】:

您正在使用this version of FirstOrDefault,它表示以下内容:

返回序列中满足条件的第一个元素,如果没有找到这样的元素,则返回默认值。

在这种情况下,您指定的条件(或“谓词”)是这样的:

x => x.Text != null

这只是说“如果Text 属性不是null,则返回true” - 对于“第一项”(基于您已经证明的数据),它将始终返回true,正如你提到的。

相反,您可能希望您的谓词仅针对具有适当ChapterTitle 的项目返回true

首先从这里更改Handle_ItemTapped

Navigation.PushAsync(new StepView(_protocol, nextTitle));

对此(这是因为我们需要 StepView 构造函数中的 tappedStep.ChapterTitle 的值用于新谓词):

Navigation.PushAsync(new StepView(_protocol, Title, tappedStep.ChapterTitle));

然后将StepView 的构造函数更新为:

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;

现在,FirstOrDefault 的谓词是:

x => x.ChapterTitle == chapterTitle

这意味着“如果ChapterTitle 属性等于chapterTitle,则返回true”。

另请注意,设置 Title 属性与您的原始代码略有不同,您可能需要对其进行调整以获得您正在寻找的确切功能。

【讨论】:

我试过你的代码,但我在handle_tapped@Donut 中得到了The name 'step' does not exist in the current context 我应该在哪里使用x =&gt; x.Text != null 啊,看来应该是轻拍了一步。 我修复了它,但现在我在lblText.Text = protocol.Contents.FirstOrDefault(x =&gt; x.Text == chapterTitle).Text; @Donut 上得到了System.NullReferenceException: 'Object reference not set to an instance of an object. 我应该用什么来根据章节获取标签中的内容

以上是关于使用啥代替 FirstOrDefault 来获取与 C# 中使用 linq 中所选章节关联的 json 文本?的主要内容,如果未能解决你的问题,请参考以下文章

First 和 FirstOrDefault , Last 和 LastOrDefault 有啥区别 [重复]

IE-11 已经贬低了与时间相关的功能。在 IE 11 中使用啥代替 t:seq 来切换图像

integer在idea中,可以用啥代替

我可以使用啥来获取整数输入而不是 C 中的 scanf?

Sequence contains no elements : LINQ error

在 CSS3 中使用啥来代替 CONTAINS()