Xamarin中ViewModel如何获取BindableLayout.ItemTemplate绑定的Entry数据
问题根源说明
- 原代码中
Entry没有绑定Text属性,输入内容无法同步到绑定的模型层,自然拿不到输入数据 - 后台代码设置
this.BindingContext = this会覆盖指向ViewModel的绑定上下文,导致ViewModel的命令、绑定全部失效
步骤1:修改Form模型类
新增存储输入内容的属性,实现属性变更通知:
public class Form : INotifyPropertyChanged { private string _name; public string name { get => _name; set { _name = value; OnPropertyChanged(); } } private string _label; public string label { get => _label; set { _label = value; OnPropertyChanged(); } } // 新增属性,存储Entry输入内容 private string _value; public string Value { get => _value; set { _value = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
步骤2:调整ViewModel代码
把接口拉取、数据集合、提交逻辑全部迁移到ViewModel中:
public class YourViewModel : INotifyPropertyChanged { private ObservableCollection<Form> _forms; public ObservableCollection<Form> forms { get => _forms; set { _forms = value; OnPropertyChanged(); } } public ICommand FormCommand => new Command(async () => await FormButton()); public YourViewModel() { // 初始化时拉取动态字段,也可以在页面生命周期中主动调用 _ = CreateCollection(); } public async Task CreateCollection() { Uri uri = new Uri("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); var formList = list.data.FirstOrDefault().form.ToList(); forms = new ObservableCollection<Form>(formList); } private async Task FormButton() { // 直接遍历集合即可拿到所有动态Entry的输入值 foreach (var item in forms) { var fieldName = item.name; var userInput = item.Value; // 处理提交逻辑即可 } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
步骤3:清理页面后台代码(xml.cs)
删掉原有业务逻辑,仅绑定上下文到ViewModel实例:
public YourPage() { InitializeComponent(); // 不要绑定到this,直接绑定ViewModel实例 this.BindingContext = new YourViewModel(); }
步骤4:修改XAML绑定规则
新增Entry的Text双向绑定:
<StackLayout BindableLayout.ItemsSource="{Binding forms}"> <BindableLayout.ItemTemplate> <DataTemplate> <!-- Entry的Name属性运行时绑定不生效,直接用模型的name字段标识即可 --> <Entry Placeholder="{Binding label}" Text="{Binding Value, Mode=TwoWay}" /> </DataTemplate> </BindableLayout.ItemTemplate> </StackLayout> <!-- 原有按钮绑定不用修改,直接生效 --> <Button x:Name="SubmitButton" Text="Submit" Command="{Binding FormCommand}">
调整完成后所有动态Entry的输入内容会实时同步到ViewModel的集合中,提交命令也可以正常触发,两个问题同步解决。
内容的提问来源于stack exchange,提问作者Stavrogin
相关产品推荐
相关产品推荐

