1

I am Trying to Write My listView (with multiple Binding Objects in it and user Entrys as input) to a Text file. I came up with the Idea of Serialize it to Json and then write it to text with button clicked (I am new here :)). But I get stocked in Json Loops errors.

The name of my listView is LL:

private void Save_Clicked(object sender, EventArgs e)
{
    string Listi = JsonConvert.SerializeObject(LL);

    File.WriteAllText(DailyTex, Listi);

    editor.Text = File.ReadAllText(DailyTex);

    DisplayAlert("Save completed", "Please Try Egain", "Continue");
}

The error is:

Newtonsoft.Json.JsonSerializationException: 'Self referencing loop detected for property 'ParentView' with type 'Xamarin.Forms.Grid'. Path 'TemplatedItems[0].View.Children[0]'.'

My Xamlpage

<ListView x:Name="LL" Grid.Row="3"   ItemsSource="{Binding energy}" HeightRequest="300" >
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>

                                    <Grid  Padding="5" BackgroundColor="White" RowSpacing="40" >
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="50"></RowDefinition>
                                            <RowDefinition Height="50"></RowDefinition>
                                        </Grid.RowDefinitions>

                                        <Label x:Name="label" HorizontalOptions="Center" Text="{Binding EE}" FontSize="18"  TextColor="Black" Grid.Column="0" Grid.Row="0" />
                                        <Entry TextChanged="Entry_TextChanged" HorizontalOptions="Center" VerticalOptions="Center" Keyboard="Numeric" Placeholder=". . . . . . . ." Grid.Column="1" Grid.Row="0" BackgroundColor="Beige" WidthRequest="80" />
                                        <Entry TextChanged="Entry_TextChanged_1" HorizontalOptions="Center" VerticalOptions="Center" Keyboard="Numeric" Placeholder=". . . . . . . ." Grid.Column="2" Grid.Row="0" BackgroundColor="Beige" WidthRequest="80"/>
                                        <Entry TextChanged="Entry_TextChanged_2" HorizontalOptions="Center" VerticalOptions="Center" Keyboard="Numeric" Placeholder=". . . . . . . ." Grid.Column="3" Grid.Row="0" BackgroundColor="Beige" WidthRequest="80"/>
                                        <BoxView Grid.Column="0" Grid.Row="0" BackgroundColor="Black" WidthRequest="1" HorizontalOptions="EndAndExpand" VerticalOptions="FillAndExpand"/>
                                        <BoxView Grid.Column="1" Grid.Row="0" BackgroundColor="Black" WidthRequest="1" HorizontalOptions="EndAndExpand" VerticalOptions="FillAndExpand"/>
                                        <BoxView Grid.Column="2" Grid.Row="0" BackgroundColor="Black" WidthRequest="1" HorizontalOptions="EndAndExpand" VerticalOptions="FillAndExpand"/>


                                    </Grid>

                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>

with a model I can now print this: Out put

  • 1
    a ListView is a complex UI object. You can't just serialize it like that. You need to serialize the data object that is the ItemsSource of your ListvView – Jason Aug 08 '21 at 17:01
  • Isn't there any NuGet to do the job? – Behzad Changizi Aug 08 '21 at 17:10
  • Yes, Newtonsoft. Serializing your ItemSource to a file will take two lines of code. – Jason Aug 08 '21 at 17:15
  • its funny listview doesn't have foreach statment... – Behzad Changizi Aug 09 '21 at 14:32
  • @BehzadChangizi - Its not an accident (or oversight) that listview doesn't support foreach. A ListView is a complicated entity, whose job is to make something appear visually. Its not intended to be worked with, the way that you attempted. In fact, it would be difficult to make that work consistently, given different platforms, and how they evolve. Don't try to extract anything from a listview. Instead, get that info from the Source that was used to create the listview. This is part of "separation of view and model". – ToolmakerSteve Aug 09 '21 at 16:09
  • Change WHAT you serialize. When the user enters values, each value should change a property in a "ViewModel". (Each value is some "Binding") Then serialize that viewmodel. See Newtonsoft.Json docs for how to "mark" properties, to indicate which ones should be serialized. – ToolmakerSteve Aug 09 '21 at 16:17
  • Thanks all. I did that toolmaker. The problem is I cant control the text file. my list view Only has 1 label that is binding to the model. but it also has Entries (empty) that will add up by the numbers of label added in model. – Behzad Changizi Aug 09 '21 at 16:54
  • LOL. I just want my list view structure in Text. or is it something You cant do? – Behzad Changizi Aug 09 '21 at 16:59

1 Answers1

0

You can set the ItemsSource of listview as collection of objects like:

    ObservableCollection<MyText> txts = new ObservableCollection<MyText>();
    MyText txt1 = new MyText();
    MyText txt2 = new MyText();
    txt1.num = "1";
    txt2.num = "2";
    txts.Add(txt1);
    txts.Add(txt2);
   ll.ItemsSource = txts;

And when you save, you can serialize the ItemsSource like:

 private void saveload_clicked(object sender, EventArgs e)
{
    string jsontxt = JsonConvert.SerializeObject(ll.ItemsSource);
    File.WriteAllText(myfile, jsontxt);
    displaytext.Text = File.ReadAllText(myfile);
    Console.WriteLine("done");
}

Here are my xaml and running screenshot:

     <ContentPage.Content>
        <StackLayout>
            <Button Text="SaveandLoad" Clicked="saveload_clicked"/>
            <Label x:Name="displaytext"/>
       <ListView x:Name="ll" SeparatorColor="Blue" RowHeight="200">
           <ListView.ItemTemplate>
               <DataTemplate>
                   <ViewCell >
                       <StackLayout>
                       <Label Text="{Binding num}" BackgroundColor="Green" WidthRequest="20"/>
                       <Entry Text="{Binding line1}"/>
                       <Entry Text="{Binding line2}"/>
                       <Entry Text="{Binding line3}"/>
                           </StackLayout>
                       </ViewCell>
               </DataTemplate>
           </ListView.ItemTemplate>
       </ListView>
            </StackLayout>
    </ContentPage.Content>
</ContentPage>

enter image description here

Adrain
  • 1,946
  • 1
  • 3
  • 7