Xamarin中CheckBox触发命令时无效转换异常的排查与解决
Xamarin中InputKit CheckBox绑定命令触发无效转换异常的解决
我在Xamarin项目中,尝试通过InputKit的CheckBox勾选时,将列表项从待办集合移除并添加到已完成集合。ImageButton绑定的RemoveTodoCommand可以正常工作,但CheckBox绑定的CompleteTodoCommand触发时,抛出「Specified cast is not valid.」(无效转换)异常。
相关代码
XAML代码
<ListView ItemsSource="{Binding TodoListItems}" x:Name="todoList"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <FlexLayout JustifyContent="SpaceBetween" Padding="20,0"> <ContentView> <FlexLayout AlignItems="Center" > <input:CheckBox IsChecked="{Binding Complete}" CheckChangedCommand="{Binding Path=BindingContext.CompleteTodoCommand, Source={x:Reference todoList}}" CommandParameter="{Binding .}" /> <Label Text="{Binding TodoText}" Padding="10,0,0,0" FontSize="Large"/> </FlexLayout> </ContentView> <ImageButton Source="trash_icon.png" Command="{Binding Path=BindingContext.RemoveTodoCommand, Source={x:Reference todoList}}" CommandParameter="{Binding .}" Scale="1.2" BackgroundColor="White" /> </FlexLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
ViewModel代码
{ private ObservableCollection<TodoItem> todoListItems; public ObservableCollection<TodoItem> TodoListItems { get { return todoListItems; } set { todoListItems = value; } } private ObservableCollection<TodoItem> completedTodoItems; public ObservableCollection<TodoItem> CompletedTodoItems { get { return completedTodoItems; } set { completedTodoItems = value; } } public TodoListViewModel() { todoListItems = new ObservableCollection<TodoItem>(); TodoListItems.Add(new TodoItem("Walk the duggo",false)); TodoListItems.Add(new TodoItem("Do the washing",false)); TodoListItems.Add(new TodoItem("Brush off Cheeto dust",false)); CompletedTodoItems = new ObservableCollection<TodoItem>(); } public ICommand AddTodoCommand => new Command(AddTodoItem); public string NewTodoInputValue { get; set; } void AddTodoItem() { TodoListItems.Add(new TodoItem(NewTodoInputValue)); } public ICommand RemoveTodoCommand => new Command(RemoveTodoItem); void RemoveTodoItem(object o) { TodoItem todoItemBeingRemoved = o as TodoItem; TodoListItems.Remove(todoItemBeingRemoved); } public ICommand CompleteTodoCommand => new Command(CompleteTodo); void CompleteTodo(object o) { TodoItem todoItemCompleted = o as TodoItem; todoListItems.Remove(todoItemCompleted); CompletedTodoItems.Add(todoItemCompleted); } }
MainPage.xaml.cs代码
public partial class MainPage : ContentPage { TodoListViewModel ViewModel { get; set; } public MainPage() { InitializeComponent(); this.ViewModel = new TodoListViewModel(); } }
异常排查
已确认ObservableCollection已完成初始化,AddTodo和RemoveTodo命令均可正常工作。异常栈追踪如下:
0x1C in TodoAppXamarin.ViewModels.TodoListViewModel.CompleteTodo at C:\Users\johns\source\repos\TodoAppXamarin\TodoAppXamarin\TodoAppXamarin\ViewModels\TodoListViewModel.cs:64,4 at C:\Users\johns\source\repos\TodoAppXamarin\TodoAppXamarin\TodoAppXamarin\ViewModels\TodoListViewModel.cs(64)
进一步排查发现,无论在何处向CompletedTodoItems集合添加TodoItem都会触发异常——即使在ViewModel构造函数中添加测试项,也会在Android项目MainActivity的OnCreate方法中抛出异常:
public TodoListViewModel() { todoListItems = new ObservableCollection<TodoItem>(); TodoListItems.Add(new TodoItem("Walk the duggo", false)); TodoListItems.Add(new TodoItem("Do the washing", false)); TodoListItems.Add(new TodoItem("Brush off Cheeto dust", false)); CompletedTodoItems = new ObservableCollection<TodoItem>(); CompletedTodoItems.Add(new TodoItem("Do the dishes",true)); }
对应异常栈:
> 0x1F in TodoAppXamarin.Droid.MainActivity.OnCreate at C:\Users\johns\source\repos\TodoAppXamarin\TodoAppXamarin\TodoAppXamarin.Android\MainActivity.cs:17,13 C#
解决方法
修改CompleteTodo方法的参数转换方式,将as安全转换改为直接强制转换后,问题得以解决:
void CompleteTodoItem(object o) { TodoItem completedTodoItem=(TodoItem)o; Console.WriteLine(completedTodoItem.TodoText); TodoListItems.Remove(completedTodoItem); CompletedTodoItems.Add(completedTodoItem as TodoItem); Console.WriteLine(CompletedTodoItems.Contains(completedTodoItem)); }
内容的提问来源于stack exchange,提问作者Michael Johnston
相关产品推荐
相关产品推荐

