Xamarin Forms中点击ListView项内ImageButton时如何选中对应项?
问题背景
在XAML中编写数据模板时,ListView列表项内嵌入了ImageButton控件,对应XAML实现代码如下:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="George.KeySave.FilesList" xmlns:localImg="clr-namespace:George.Image" Title="KeySave"> <ContentPage.Content> <ListView x:Name="Flist" ItemSelected="Flist_ItemSelected"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal" Padding="5,0,0,0"> <Label x:Name="SelFileName" Text="{Binding fname}" FontSize="Medium" TextColor="Blue" VerticalOptions="Center"/> <ImageButton HeightRequest="33" WidthRequest="33" Source="{localImg:Emb ResId=George.Image.deer.png}" x:Name="delete" Clicked="delete_Clicked" HorizontalOptions="EndAndExpand"/> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </ContentPage.Content> </ContentPage>
现有代码存在逻辑bug:点击第二项的文本区域,将第二项设为ListView当前选中项后,再点击第一项的ImageButton,会因为选中项仍停留在第二项,导致错误操作第二个文件。
对应的ImageButton.Click、ListView.ItemSelected事件后台代码如下:
public partial class FilesList : ContentPage { private void delete_Clicked(object sender, EventArgs e) { DisplayAlert("delete file", $"{TdelFile.fname}", "ok"); } listdatas TdelFile; private void Flist_ItemSelected(object sender, SelectedItemChangedEventArgs e) { var delFile = e.SelectedItem as listdatas; TdelFile = delFile; } }
问题表现
当第二项处于选中状态时,点击第一项的ImageButton,弹窗提示的待删除文件并非第一项对应文件,操作目标匹配错误,异常效果如下图:
故障原因
删除逻辑完全依赖ListView全局选中项存储的TdelFile变量,但点击列表项内部的ImageButton时,不会触发ListView的ItemSelected事件切换选中项,此时全局存储的选中项还是之前选中的第二项,自然会读取到错误的操作对象。
修复方案
不要依赖ListView的全局选中状态获取按钮对应行的数据,直接从点击事件触发源的绑定上下文获取当前行对应的数据源,修改方式如下:
- 重写
delete_Clicked事件方法,直接从触发点击的ImageButton的BindingContext属性获取当前行绑定的listdatas对象,无需全局存储TdelFile变量,也不需要依赖ItemSelected事件给删除逻辑传参:
private void delete_Clicked(object sender, EventArgs e) { // 被点击的ImageButton的绑定上下文,就是当前行对应的数据源对象 var targetFile = (sender as ImageButton).BindingContext as listdatas; DisplayAlert("delete file", $"{targetFile.fname}", "ok"); }
- 可选优化:如果业务不需要ListView的行选中高亮效果,可以直接移除XAML中ListView绑定的
ItemSelected="Flist_ItemSelected"事件,同时删除后台对应的事件方法和全局TdelFile变量,避免多余的选中状态逻辑造成干扰。
注意:所有放在ListView、CollectionView数据模板内的可交互控件,行级操作都优先通过控件自身的BindingContext获取当前行绑定数据,不要依赖列表的全局选中属性,就能彻底避免这类行操作错位的问题。
内容的提问来源于stack exchange,提问作者jjctw1969
相关产品推荐
相关产品推荐

