在Xamarin.Forms中创建带多按钮卡片列表并获取项ID的技术问询
解决CollectionView卡片点击获取项ID的问题
我想创建如图所示的卡片列表,支持多个点击事件并能获取对应卡片的项ID,找过开源代码和NuGet包但没解决。用CollectionView时,没法获取卡片对应的项ID,给Label设x:Name也没用。附上我的XAML代码:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage.Resources> <converters:ByteArrayToImageSourceConverter x:Key="ByteArrayToImage" /> </ContentPage.Resources> <ContentPage.Content> <Grid.ColumnDefinitions> </Grid.ColumnDefinitions> <Image.GestureRecognizers HeightRequest="30" WidthRequest="30"> </Image.GestureRecognizers> <CollectionView ItemsSource="{Binding Items}"> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Horizontal" /> </CollectionView.ItemsLayout> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Padding="0" Margin="2"> <Grid> <StackLayout Padding="0" Margin="5,25,10,0" HorizontalOptions="Center"> <Frame BackgroundColor="White" HeightRequest="440" WidthRequest="330" HasShadow="True" Padding="5" Margin="0"> <StackLayout> <Label x:Name="lblMessage" HorizontalOptions="StartAndExpand" Text="Rep:" IsVisible="false"></Label> <StackLayout HeightRequest="100" WidthRequest="320" Orientation="Horizontal" HorizontalOptions="Fill"> <Frame HeightRequest="100" WidthRequest="320" BackgroundColor="Transparent" Padding="0" Margin="0"> <ImageButton Source="{Binding ImagemVideo, Converter={StaticResource ByteArrayToImage}}" Aspect="AspectFill" Margin="0" Clicked="Video_Clicked"/> </Frame> </StackLayout> <Frame BorderColor="Transparent" BackgroundColor="White" HorizontalOptions="CenterAndExpand"> <Label Grid.Column="0" TextColor="#000000" Text="{Binding NomeTreino}" FontAttributes="None" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Start" Margin="8,0,10,10" FontSize="Medium"/> </Frame> <Frame BorderColor="LightGray" BackgroundColor="White" HorizontalOptions="StartAndExpand"> <Label Grid.Row="2" HorizontalOptions="StartAndExpand" Text="{Binding Descricao}"/> </Frame> <StackLayout Padding="0" Margin="5,5"> <Grid Visual="Material"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="65"/> <RowDefinition Height="65"/> </Grid.RowDefinitions> <Frame Grid.Row="0" Visual="Material" Grid.Column="0" BorderColor="LightGray"> <StackLayout > <Label HorizontalOptions="StartAndExpand" Text="Carga:"></Label> <Label HorizontalOptions="CenterAndExpand" Text="{Binding cargaInicial}"></Label> </StackLayout> </Frame> <Frame Grid.Row="0" Grid.Column="1" BorderColor="LightGray"> <StackLayout > <Label HorizontalOptions="StartAndExpand" Text="Séries:"></Label> <Label HorizontalOptions="CenterAndExpand" Text="{Binding serie1}"></Label> </StackLayout> </Frame> <Frame Grid.Row="0" Grid.Column="2" BorderColor="LightGray"> <StackLayout > <Label HorizontalOptions="StartAndExpand" Text="Rep:"></Label> <Label HorizontalOptions="CenterAndExpand" Text="{Binding repeticao1}"></Label> </StackLayout> </Frame> <Frame Grid.Row="1" Grid.Column="0" BorderColor="LightGray"> <StackLayout > <Label Text="{Binding tempoIntervalo}" ></Label> </StackLayout> </Frame> <Frame Grid.Row="1" Grid.Column="2" BorderColor="LightGray"> <StackLayout > <ImageButton BackgroundColor="White" Source="Checkblue.png" Aspect="Fill" HeightRequest="20" WidthRequest="20" Margin="0" Clicked="BtnCheck_Clicked"/> </StackLayout> </Frame> </Grid> </StackLayout> </StackLayout> </Frame> </StackLayout> </Grid> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ScrollView> </StackLayout> </ContentPage.Content>

解决方案
方法1:在Clicked事件中直接获取绑定项
每个点击控件的Clicked事件里,可通过BindingContext拿到当前绑定的数据项,进而提取ID:
后台代码示例:
private void Video_Clicked(object sender, EventArgs e) { // 替换成你实际的数据模型类 var currentItem = (TrainingItem)((ImageButton)sender).BindingContext; int itemId = currentItem.Id; // 这里编写视频按钮的点击逻辑 } private void BtnCheck_Clicked(object sender, EventArgs e) { var currentItem = (TrainingItem)((ImageButton)sender).BindingContext; int itemId = currentItem.Id; // 这里编写勾选按钮的点击逻辑 }
注意:要确保你的数据模型类(比如TrainingItem)包含用于标识的ID属性。
方法2:用MVVM模式绑定Command(推荐)
如果采用MVVM架构,建议给按钮绑定Command和CommandParameter,直接把当前项作为参数传递:
修改XAML中的按钮代码:
<!-- 视频按钮 --> <ImageButton Source="{Binding ImagemVideo, Converter={StaticResource ByteArrayToImage}}" Aspect="AspectFill" Margin="0" Command="{Binding BindingContext.VideoCommand, Source={x:Reference Name=MainPage}}" CommandParameter="{Binding .}"/> <!-- 勾选按钮 --> <ImageButton BackgroundColor="White" Source="Checkblue.png" Aspect="Fill" HeightRequest="20" WidthRequest="20" Margin="0" Command="{Binding BindingContext.CheckCommand, Source={x:Reference Name=MainPage}}" CommandParameter="{Binding .}"/>
同时给你的ContentPage设置x:Name="MainPage",然后在ViewModel中定义命令:
public ICommand VideoCommand { get; } public ICommand CheckCommand { get; } public YourViewModel() { VideoCommand = new Command<TrainingItem>(ExecuteVideoCommand); CheckCommand = new Command<TrainingItem>(ExecuteCheckCommand); } private void ExecuteVideoCommand(TrainingItem item) { int itemId = item.Id; // 处理视频点击逻辑 } private void ExecuteCheckCommand(TrainingItem item) { int itemId = item.Id; // 处理勾选逻辑 }
关键说明
- DataTemplate里的控件属于模板实例,通过
x:Name直接访问后台会失效,这是设计特性,不要用这种方式拿数据。 - 不需要额外的NuGet包或开源代码,用Xamarin.Forms自带的CollectionView和绑定机制就能解决问题。
内容的提问来源于stack exchange,提问作者Wesley Henrique dos Santos
相关产品推荐
相关产品推荐

