Reputation: 143
I had an Issue in Dynamically adding Entry Controls, which Wendy Zang - MSFT helped and solved it.
The code to Get the list of entries from API is written in .xml.cs
page, and in .xml
page, the Bindablelayout.ItemTemplate of StackLayout is being used to setup the template of Entry.
It's working perfectly, but the Code to Submit the Form is written in ViewModel
.
When I paste the code of .xml.cs
page in ViewModel
, I can't get the Entries and when the code is in xml.cs
for which I have to set the this.BindingContext = this;
code in the ViewModel
isn't executing.
.xml
<StackLayout BindableLayout.ItemsSource="{Binding forms}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Entry Name="{Binding name}" Placeholder="{Binding label}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
xml.cs
RootObject list = JsonConvert.DeserializeObject<RootObject>(fields);
forms = new List<Form>();
forms = list.data.FirstOrDefault().Form.ToList();
this.BindingContext = this;
Button in XAML & ViewModel
<Button
x:Name="SubmitButton"
Text="Submit"
Command="{Binding FormCommand}">
public ICommand FormCommand=> new Command(async (x) => await FormButton(default, default));
UPDATE
Code to fetch the dynamic fields from server.
public async Task CreateCollection()
{
Uri uri = new Uri(string.Format("http://example.com/entry"));
HttpClient httpClient = new HttpClient(new NativeMessageHandler());
HttpResponseMessage response = await httpClient.GetAsync(uri);
string entries = await response.Content.ReadAsStringAsync();
RootObject list = JsonConvert.DeserializeObject<RootObject>(entries);
form = new List<Form>();
form = list.data.FirstOrDefault().form.ToList();
}
Upvotes: 0
Views: 1350
Reputation: 143
For complete understanding, have a look at @Wendy's solution. The problem was that, Form wasn't appearing when Page opens up, but when I was in Debug Mode, and refresh the .xml
page, it appears.
@Shaw recommend to use ObservableCollection<>
instead of List<>
, but on list.data.FirstOrDefault().form.ToList();
it said cannot convert 'System.Collection.Generic.List<>' to 'System.Collections.ObjectModel.ObservableCollection<>'.
I fixed it.. here is the complete solution.
private ObservableCollection<Form> _forms = new ObservableCollection<Form>();
public ObservableCollection<Form> Forms
{
get
{
return _forms;
}
set
{
this.RaiseAndSetIfChanged(ref _forms, value);
}
}
var list = JsonConvert.DeserializeObject<Rootobject>(json);
foreach (var i in list.data.Where(c => c.id == ""))
{
_forms.Add(i.form.ToList());
}
Upvotes: 0
Reputation: 10948
If you want to do this with ViewModel, you could refer to the code below.
Xaml:
<StackLayout>
<Button
x:Name="SubmitButton"
Text="Submit"
Command="{Binding FormCommand}"></Button>
<StackLayout x:Name="DynamicEntry" BindableLayout.ItemsSource="{Binding forms}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Entry Placeholder="{Binding label}" MaxLength="{Binding max_length}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
Code behind:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
this.BindingContext = new ViewModel();
}
}
ViewModel:
public class ViewModel
{
public List<Form> forms { get; set; }
public ICommand FormCommand { get; set; }
public ViewModel()
{
CreateCollection();
FormCommand = new Command(async (x) => await FormButton(default, default));
}
private Task FormButton(object p1, object p2)
{
return Task.Delay(2000);
}
public void CreateCollection()
{
var json = @"{
'success': 'true',
'data': [
{
'form': [
{
'label': 'Name',
'name': 'name',
'type': 'text',
'max_length': '15',
'required': 'true'
},
{
'label': 'Email',
'name': 'email',
'type': 'email',
'max_length': '30',
'required': 'true'
}
]
}
]
}";
var list = JsonConvert.DeserializeObject<Rootobject>(json);
forms = new List<Form>();
forms = list.data.FirstOrDefault().form.ToList();
}
}
Output:
Upvotes: 2