Xamarin Forms绑定对象添加全局值时出现无效转换异常
问题场景与异常
尝试构建包含重复自定义Entry的布局:外层通过BindableLayout循环渲染多个Entry组件,输入文本时显示SuggestedText候选列表(ViewModel构造时初始化的ObservableCollection<string>)。静态绑定数据源时功能正常,但动态绑定SuggestedText时,页面导航前抛出异常:
System.InvalidCastException: Specified cast is not valid. at Xamarin.Forms.BindableLayout+<>c.<.cctor>b__19_4 (Xamarin.Forms.BindableObject b) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\BindableLayout.cs:24 at Xamarin.Forms.BindableObject.CreateAndAddCo...
即使将SuggestedText移至MyObjectLists中,异常仍会触发。
错误根源
- ListView误用BindableLayout模板:
BindableLayout.ItemTemplate仅适用于布局控件(如StackLayout、Grid),ListView自身拥有独立的ItemTemplate属性,混用两者会导致Xamarin.Forms内部类型转换失败,直接引发InvalidCastException。 - ViewModel中集合未初始化:
SuggestedText在调用FillSuggestText()添加元素前未实例化,存在空引用风险。 - 数据上下文不匹配:外层
BindableLayout的数据源是ObservableCollection<string>,模板内Entry绑定LicensePlate属性时,当前上下文是string类型,不存在该属性,会导致绑定失败。
解决方案
1. 修正ListView的模板定义
将ListView内部的BindableLayout.ItemTemplate替换为原生ListView.ItemTemplate,且必须用ViewCell包裹内容:
<ListView ItemsSource="{Binding Path=BindingContext.SuggestedText, Source={x:Reference thispage}}" x:Name="LicensePlateListView" IsVisible="{Binding IsVisible}" CachingStrategy="RecycleElement" BackgroundColor="White" ItemTapped="OnItemTapped" AbsoluteLayout.LayoutBounds="20,110,269,160" AbsoluteLayout.LayoutFlags="None"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout BackgroundColor="White"> <Label Text="{Binding .}" FontSize="16" TextColor="#FF464859"/> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
2. 初始化ViewModel中的ObservableCollection
在ViewModel构造函数中提前实例化SuggestedText,避免空引用:
public MyViewModel (MyObject parameters, INavigation navigation) { MyObjectLists = parameters; // 提前初始化集合 SuggestedText = new ObservableCollection<string>(); Device.BeginInvokeOnMainThread(() => { try { FillSuggestText(); } catch (Exception ex) { IsBusy = false; Helper.GlobalErrorTrashing(ex); } }); }
3. 修正数据上下文绑定
外层BindableLayout的数据源ListofLicensePlates若为ObservableCollection<string>,则Entry的Text绑定应改为{Binding .};若需要LicensePlate和Index属性,需将集合元素改为自定义类:
// 定义LicensePlateItem类 public class LicensePlateItem { public string LicensePlate { get; set; } public int Index { get; set; } public bool IsVisible { get; set; } } // 更新MyObject中的集合类型 public class MyObject { public List<TextObject> TextList { get; set; } public ObservableCollection<LicensePlateItem> ListofLicensePlates { get; set; } }
验证
- 编译运行修正后的代码
- 导航至目标页面,确认无初始化异常
- 输入文本触发
ShowListView,检查候选列表是否正常显示
内容的提问来源于stack exchange,提问作者Amature123
相关产品推荐
相关产品推荐

