Home > OS >  What to use instead of FirstOrDefault to get the json text associated with the chosen chapter in C#
What to use instead of FirstOrDefault to get the json text associated with the chosen chapter in C#

Time:11-11

I have a program where the user has to get the text from json based on the chapter clicked within the protocol by the listview item (the chapters)

How do i fix this?

Here the user selects the chosen chapter within the 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;
        var nextTitle = Title   " - "   tappedStep.ChapterTitle;
        Navigation.PushAsync(new StepView(_protocol, Title, tappedStep.ChapterTitle));
        //Deselect item
        ((ListView)sender).SelectedItem = null;
    }

What goes wrong next is that the label text is ALWAYS the first text of the very first chapter this is because I use FirstOrDefault in the next class StepView.cs the logic here will have to be such that it takes the text that belongs to the corresponding chapter! Instead of the very first one within the protocol.

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());
    }

This is the json I use

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

And this are my Domain Classes

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; }
}

How can I make the label text, instead of FirstOrDefault, the text that belongs to the beginning of the selected chapter?

CodePudding user response:

You're using this version of FirstOrDefault, which says the following:

Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.

In this case, the condition you're specifying (or "predicate") is this:

x => x.Text != null

This just says "return true if the Text property is not null" -- which will always return true for the "very first item" (based on the data you've proved), as you mentioned.

Instead, you probably want your predicate to return true only for the item with the appropriate ChapterTitle.

Start by changing Handle_ItemTapped from this:

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

To this (this is because we need the value of tappedStep.ChapterTitle in the StepView constructor for the new predicate):

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

Then update the constructor for StepView to this:

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;
}

Now, the predicate for FirstOrDefault is:

x => x.ChapterTitle == chapterTitle

Which means "return true if the ChapterTitle property is equal to chapterTitle".

Also note that setting the Title property is slightly different from your original code, you may need to adjust this to get the exact functionality you're looking for.

  • Related