在 Xamarin 的 ViewModel 中绑定来自 Bindablelayout.ItemTemplate 的数据
Posted
技术标签:
【中文标题】在 Xamarin 的 ViewModel 中绑定来自 Bindablelayout.ItemTemplate 的数据【英文标题】:Bind Data from Bindablelayout.ItemTemplate in ViewModel in Xamarin 【发布时间】:2021-08-02 15:34:58 【问题描述】:我在Dynamically adding Entry Controls 中遇到了一个问题,Wendy Zang - MSFT 帮助并解决了它。
从API获取条目列表的代码写在.xml.cs
页面中,在.xml
页面中,StackLayout的Bindablelayout.ItemTemplate用于设置条目模板。
它运行良好,但提交表单的代码写在ViewModel
。
当我将.xml.cs
页面的代码粘贴到ViewModel
时,我无法获取条目,并且当代码在xml.cs
中时,我必须在ViewModel
中设置this.BindingContext = this;
代码没有执行。
.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;
XAML 和 ViewModel 中的按钮
<Button
x:Name="SubmitButton"
Text="Submit"
Command="Binding FormCommand">
public ICommand FormCommand=> new Command(async (x) => await FormButton(default, default));
更新
从服务器获取动态字段的代码。
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();
【问题讨论】:
您的 xaml 文件中有<ContentPage.Content>
吗?如果是这样,应该是this.Content.BindingContent = this;
@Shaw 感谢您的回复,我使用了这个但仍然无法在ViewModel
中提交表单(我从.xml
页面和ViewModel
发布了按钮代码示例).. 如果有在xml.cs
中不是this.Content.BindingContent = this;
,那么它是可点击的,否则它不是
如果我在ViewModel
中粘贴xml.cs
代码(从api 获取条目),则无法查看条目..
去掉“x”,改成async () =>
。如果列表绑定没问题,继续使用之前的绑定代码。
@Shaw 我尝试了 Wendy 的解决方案,当应用程序处于调试模式时,我刷新 .xml
页面,出现表单,否则它不会在第一次出现页面时出现.. 任何想法为什么会这样?
【参考方案1】:
如果你想用 ViewModel 做这个,你可以参考下面的代码。
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>
后面的代码:
public partial class MainPage : ContentPage
public MainPage()
InitializeComponent();
this.BindingContext = new 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();
输出:
【讨论】:
嗨,我使用了静态 JSON 条目,它工作正常,但是当我从 api 获取条目时,无法在视图中获取它(虽然我可以从 api 获取条目)。 当应用程序处于调试模式时,我刷新.xml
页面,出现表单..为什么会这样?以及如何解决这个问题?
我创建了CreateCollection()
函数,包括void
和async
并且还在MainThread.BeginInvokeOnMainThread
和Device.BeginInvokeOnMainThread
中编写了api 调用/响应。但仍然没有显示页面出现时表单,但是当我刷新.xml
页面时(当它处于调试模式时,与PC连接时),它出现...
@Stavrogin 1. 尝试在OnAppearing
中调用CreateCollection()
方法而不是构造函数。 2.尽量用ObservableCollection<Form> Forms
代替list
在OnAppearing
中调用CreateCollection()
方法没有任何区别,我使用了ObservableCollection<Form> Forms
但在list.data.FirstOrDefault().form.ToList();
上它说无法转换'System.Collection.Generic.List' 到 'System.Collections.ObjectModel.ObservableCollection'【参考方案2】:
要全面了解,请查看@Wendy's 解决方案。问题是,打开页面时表单没有出现,但是当我处于调试模式并刷新 .xml
页面时,它出现了。
@Shaw 建议使用ObservableCollection<>
而不是List<>
,但在list.data.FirstOrDefault().form.ToList();
上它说无法将'System.Collection.Generic.List' 转换为'System.Collections.ObjectModel.ObservableCollection '.
我修好了..这是完整的解决方案。
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());
【讨论】:
如果form = list.data.FirstOrDefault().form.ToList();
以前有效,您应该可以改用form = new ObservableCollection<Form>(list.data.FirstOrDefault().form);
。但是我不太确定list.data.FirstOrDefault().form
的类型以上是关于在 Xamarin 的 ViewModel 中绑定来自 Bindablelayout.ItemTemplate 的数据的主要内容,如果未能解决你的问题,请参考以下文章
如何绑定到CarouselView(Xamarin.Forms)(MVVM)内部的ViewModel元素?
绑定到 ViewModel 在 Xamarin.Forms 中不起作用
从 ViewModel 绑定到 Xamarin.Forms.Maps.Map
Xamarin.Forms 无法通过 ViewModel 将 ObservableCollection 绑定到 CollectionList