Xamarin MVVM架构下如何将CollectionView中Picker数据提交至API
解决CollectionView嵌套Picker无法获取选中值的MVVM方案
我看了你的代码,问题出在几个关键的绑定和设计上,导致ViewModel拿不到Picker的选中值。下面一步步给你修正:
核心问题分析
- Picker绑定错误:你把
SelectedItem绑定到了vraag_id(问题ID),这完全不对——vraag_id是每个问题的标识,不是用户选中的选项,所以用户选完后根本不会更新任何有用的数据。 - ViewModel设计不符合动态问卷需求:你提前定义了
vraag_127、vraag_128这些固定属性,但问卷是后端动态加载的,这些属性根本没有和UI绑定,自然永远是null。 - 模型未实现属性变更通知:你的
Vragen类没有实现INotifyPropertyChanged,就算绑定对了,ViewModel也接收不到选中值的变化。
分步代码修正
1. 修正模型类,添加属性变更通知
首先让你的模型类实现INotifyPropertyChanged,并且给每个问题添加SelectedAnswer属性来存储选中的选项:
using System.ComponentModel; using System.Runtime.CompilerServices; public class Questionaire_model : INotifyPropertyChanged { public int id { get; set; } public string default_question { get; set; } public string description { get; set; } private IList<Vragen> _vraag; public IList<Vragen> Vraag { get => _vraag; set { _vraag = value; OnPropertyChanged(); } } public class Vragen : INotifyPropertyChanged { public string categorie_vraag { get; set; } private antwoorden _selectedAnswer; // 存储选中的整个选项对象,方便后续取分数或文本 public antwoorden SelectedAnswer { get => _selectedAnswer; set { _selectedAnswer = value; OnPropertyChanged(); } } public string vraagstelling { get; set; } public string vraag_id { get; set; } private IList<antwoorden> _antwoorden; public IList<antwoorden> Antwoorden { get => _antwoorden; set { _antwoorden = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class antwoorden { public string score_antwoord { get; set; } public string antwoord_vraagstelling { get; set; } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 修正XAML中的Picker绑定
把Picker的SelectedItem绑定到每个问题的SelectedAnswer属性,并且明确设置Mode=TwoWay(确保UI变化同步到ViewModel):
<Picker Style="{StaticResource PickRegularSmall}" SelectedItem="{Binding SelectedAnswer, Mode=TwoWay}" ItemsSource="{Binding Antwoorden}" ItemDisplayBinding="{Binding antwoord_vraagstelling}"/>
注意:这里
SelectedItem绑定的是整个antwoorden对象,如果你只需要存储选项的分数或文本,可以把SelectedAnswer类型改成string,然后绑定SelectedValue和SelectedValuePath,比如:<Picker SelectedValue="{Binding SelectedAnswerValue, Mode=TwoWay}" SelectedValuePath="score_antwoord" ItemsSource="{Binding Antwoorden}" ItemDisplayBinding="{Binding antwoord_vraagstelling}"/>对应的
Vragen类里添加public string SelectedAnswerValue { get; set; }
3. 重构ViewModel,移除固定属性并修改保存逻辑
删掉那些固定的vraag_xxx属性,直接从动态加载的Questionaire.Vraag集合中收集选中答案:
// 移除这些无用的固定属性: // public string vraag_127 { get; set; } // public string vraag_128 { get; set; } // ... // public string vraag_161 { get; set; } public ICommand SaveVragenlijstCompetentiesCommand { get { return new Command(async () => { // 遍历所有问题,收集问题ID和对应的选中答案(分数或文本) var answerData = Questionaire.Vraag.ToDictionary( q => q.vraag_id, q => q.SelectedAnswer?.score_antwoord // 根据API需求,换成antwoord_vraagstelling也可以 ); // 把收集到的字典传给API服务 var responseBool = await _apiServices.SaveCompetenties(answerData); }); } }
4. 调整API服务的保存方法
你的SaveCultuur方法现在是接收单个参数,需要改成接收字典或对应的DTO,比如:
public async Task<bool> SaveCompetenties(Dictionary<string, string> answerData) { // 把字典转换成API需要的JSON格式,然后发送请求 var json = JsonConvert.SerializeObject(answerData); // 后续请求逻辑... }
额外注意事项
- 确保你的
Questionaire_viewmodel基类(或者自身)正确实现了INotifyPropertyChanged,否则Questionaire属性变化时UI不会更新。 - 如果需要默认选中某个选项,可以在加载问卷后,给对应
Vragen的SelectedAnswer赋值。
内容的提问来源于stack exchange,提问作者Mitchell
相关产品推荐
相关产品推荐

