Xamarin将新行添加到JSON

时间:2019-02-05 13:41:27

标签: c# xamarin

想知道是否有人可以为我寻找的解决方案提供帮助。在我的Xamarin项目中,我有一个“添加另一行”按钮,该按钮在其下方添加了另一个堆栈布局,并具有与第一个相同的控件。我想将新添加的内容保存到JSON,但不知道从哪里开始,有人做过吗?

我已将第一个堆栈添加到json,但我需要它来计算按钮按下时的新堆栈。 (对不起,如果没有意义的话)

Page.xaml代码:

<Grid Margin="0, 30, 0, 30">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Label x:Name="NameLabel" Text="Name" TextColor="Black" FontSize="20" Grid.Column="0" Grid.Row="0" />
                <Label x:Name="ArrivalLabel" Text="Arrival" TextColor="Black" FontSize="20" Grid.Column="1" Grid.Row="0" />
                <Label x:Name="DescriptionLabel" Text="Description" TextColor="Black" FontSize="20" Grid.Column="2" Grid.Row="0" />
                <Label x:Name="DepartLabel" Text="Depart" TextColor="Black" FontSize="20" Grid.Column="3" Grid.Row="0" />
                <Label x:Name="SignLabel" Text="Sign" TextColor="Black" FontSize="20" Grid.Column="4" Grid.Row="0" />
            </Grid>
            <StackLayout x:Name="AddMoreNotes">
                <StackLayout>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Entry x:Name="Name" FontSize="20" Grid.Column="0" Grid.Row="0" />
                        <TimePicker x:Name="Arrival" FontSize="20" Grid.Column="1" Grid.Row="0" />
                        <Entry x:Name="Description" FontSize="20" Grid.Column="2" Grid.Row="0" />
                        <TimePicker x:Name="Depart" FontSize="20" Grid.Column="3" Grid.Row="0" />
                        <Entry x:Name="Sign" FontSize="20" Grid.Column="4" Grid.Row="0"/>
                    </Grid>
                </StackLayout>
                <!--Add More View Spawns Here Do Not Change-->
            </StackLayout>

            <StackLayout Orientation="Horizontal" HorizontalOptions="End">
                <Button x:Name="AddMoreButton" Text="Add More" FontSize="16" BorderRadius="6" Clicked="AddMoreButton_Clicked" />
            </StackLayout>

Page.xaml.cs代码:

private void AddMoreButton_Clicked(object sender, EventArgs e)
    {
        AddMoreNotes.Children.Add(new AttendanceAddMoreView()
        {

        });
    }

    private void SubmitButton_Clicked(object sender, EventArgs e)
    {
        var attendanceChecklist = new AttendanceChecklist();
        var AttentionOf1 = new List<AttentionOf>();
        var AttendanceSection1 = new List<AttendanceSection>();

        attendanceChecklist.TheDate = TheDate.Date;
        attendanceChecklist.AttendanceNumber = AttendanceNumber.Text;
        attendanceChecklist.EmployeeName = EmployeeName.Text;

        AttentionOf1.Add(new AttentionOf()
        {
            FirstName = FirstName.Text,
            LastName = LastName.Text,
            AddressLine1 = AddressLine1.Text,
            AddressLine2 = AddressLine2.Text,
            CityOrTown = CityOrTown.Text,
            County = County.Text,
            Postcode = Postcode.Text,
            ContractTitleOrRef = ContractTitleOrRef.Text,
            CustomerName = CustomerName.Text,
            SiteContact = SiteContact.Text,
        });

        AttendanceSection1.Add(new AttendanceSection()
        {
            Name = Name.Text,
            Arrival = Arrival.Time,
            Description = Description.Text,
            Depart = Depart.Time,
            Sign = Sign.Text
        });

        attendanceChecklist.attentionOf = AttentionOf1;
        attendanceChecklist.attendanceSection = AttendanceSection1;
        var json = JsonConvert.SerializeObject(attendanceChecklist, Newtonsoft.Json.Formatting.Indented);

        var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        var filename = Path.Combine(documents, "AttendanceNote.json");
        File.WriteAllText(filename, json);
        }

编辑:

添加了新代码

public string LargerJsonString;

private void AddMoreButton_Clicked(object sender, EventArgs e)
    {
        AddMoreNotes.Children.Add(new AttendanceAddMoreView()
        {

        });
        StringContent content = new StringContent(JsonConvert.SerializeObject(AddMoreNotes), Encoding.UTF8, "application/json");
        LargerJsonString += content;
    }

2 个答案:

答案 0 :(得分:0)

对不起,我无法对此发表评论,所以我在这里留下我的想法:首先,我将使用ListView,因为它可以让您轻松地将项目绑定到ListView。下面是一个小例子

<ListView x:Name="MainList" ItemsSource="{Binding Messages}" BackgroundColor="Transparent" HasUnevenRows="True" SeparatorVisibility="Default" Margin="0, 15, 0, 0" IsPullToRefreshEnabled="True" RefreshCommand="{Binding RefreshingMessages}" IsRefreshing="{Binding IsRefreshing}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.View>
                            Put your code in here
                        </ViewCell.View>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

如果在MVVM(从模型视图到视图模型)的MVVM中执行此操作,它将使工作变得更加轻松。但是我不认为这是必要的。如果您想向JSON添加另一行,我看到您已经在使用JsonConvert,因此您不能将JSON反序列化为对象列表并遍历该列表并在其中输出许多项目您的屏幕?

string JsonContent = await WhateverYourJsonIs.Content.ReadAsStringAsync().ConfigureAwait(false);
var something = JsonConvert.DeserializeObject<List<WhateverYourObjectIsCalled>>(JsonContent)

我不确定这是否是您要实现的目标,如果没有,请告诉我,我将尽力提供帮助!在这种情况下,WhateverYourJsonIs很可能需要是Json的字符串,您可能不需要该行,在从服务器返回信息的情况下,我确实需要将其读取为字符串,但是您可能不需要已经是一个字符串,这将对您进行一些测试,因为我还没有这样做,所以我从代码中截取了一些代码。希望这会有所帮助!

编辑:

如果您序列化对象并使用此方法获取字符串列表

StringContent content = new StringContent(JsonConvert.SerializeObject(NewItem), Encoding.UTF8, "application/json");

这将为您将其转换为Json,然后您可以将其附加到较大的Json字符串的末尾,例如:

LargerJsonString += content

然后将其添加到您的文件中。或者,您可以使用诸如SQLite之类的东西并将其存储在本地数据库表中?这是我使用的方法

编辑2

因此,我对Docs.Microsoft进行了一些挖掘,试图找到您要用于“ File.WriteAllText”的内容,然后发现了该方法,该方法会将多余的文本附加到文件的末尾

string appendText = "This is extra text" + Environment.NewLine;
File.AppendAllText(path, appendText);

尝试使用它而不是WriteAll

答案 1 :(得分:0)

要开始此操作,我已经在MVVM中完成了此操作,因此如果您尚未使用它,则可能必须使用它。

现在,我制作了一个虚拟布局和一个虚拟模型,如下所示:

  public class DefaultModel : INotifyPropertyChanged
{
    private string userName = string.Empty;
    private string description = string.Empty;
    private string sign = string.Empty;
    private TimeSpan arrival = TimeSpan.Zero;
    private TimeSpan depart = TimeSpan.Zero;

    public string Name
    {
        get
        {
            return userName;
        }
        set
        {
            userName = value;
            RaisePropertyChanged(nameof(Name));
        }
    }

    public TimeSpan Arrival
    {
        get
        {
            return arrival;
        }
        set
        {
            arrival = value;
            RaisePropertyChanged(nameof(Arrival));
        }
    }

    public string Description
    {
        get
        {
            return description;
        }
        set
        {
            description = value;
            RaisePropertyChanged(nameof(Description));
        }
    }

    public TimeSpan Depart
    {
        get
        {
            return depart;
        }
        set
        {
            depart = value;
            RaisePropertyChanged(nameof(Depart));
        }
    }

    public string Sign
    {
        get
        {
            return sign;
        }
        set
        {
            sign = value;
            RaisePropertyChanged(nameof(Sign));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property.
    // The CallerMemberName attribute that is applied to the optional propertyName
    // parameter causes the property name of the caller to be substituted as an argument.
    private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

我将BindingMode用作TwoWay,以便将View上的任何更改都反映到ViewModel Collection中,反之亦然

我使用的DummyModel如下所示:

MainPage.Xaml.cs

我正在使用INotifyPropertyChanged接口来通知属性中的任何更改。为了更好地理解,请检查以下内容:https://docs.microsoft.com/en-us/dotnet/framework/winforms/how-to-implement-the-inotifypropertychanged-interface

在您的MainViewModel中,将构造函数中的BindingContext设置为public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new MainViewModel(); } }

 public class MainViewModel : BindableObject
{
    public Command AddButton { get; set; }
    private ObservableCollection<DefaultModel> defaultModels;
    public ObservableCollection<DefaultModel> DefaultModels
    {
        get { return defaultModels; }
        set
        {
            defaultModels = value;
            OnPropertyChanged(nameof(DefaultModels));
        }
    }

    public MainViewModel()
    {
        DefaultModels = new ObservableCollection<DefaultModel>();
        DefaultModels.Add(new DefaultModel());
        AddButton = new Command(AddButtonCommand);
    }

    private void AddButtonCommand(object obj)
    {
        DefaultModels.Add(new DefaultModel());
    }
}

现在在您的ViewModel中执行以下操作:

AddButtonCommand

现在,如何在AddButton上非常简单地单击我调用DefaultModels并初始化一个空白对象并将其添加到ObservableCollection中,然后更新我的View并添加另一组控件以获取此数据您可以从module.power(true)集合中获取所有数据。

好运

查询时还原