WinUI中如何获取GridView点击项作为UIElement实现ConnectedAnimation
WinUI中获取GridView点击项UIElement以实现ConnectedAnimation的方法
场景说明
主页面中有一个GridView,其项绑定到DisplayedImage类的列表/数组:
<GridView x:Name="ImageListBox" ItemsSource="{x:Bind displayedImages}" ItemClick="ImageListBox_ItemClick"> <GridView.ItemTemplate> <DataTemplate x:DataType="data:DisplayedImage"> <Border> <Image x:Name="ImageBoxMain" Source="{x:Bind ImagePath }"/> </Border> </DataTemplate> </GridView.ItemTemplate> </GridView>
每个项显示从网络JSON获取的链接下载的图片(内容会频繁变化),点击网格中的图片后,应用导航到新页面显示该图片的放大版本及更多详情。
期望目标
使用ConnectedAnimation实现从GridView小图到新页面大图的过渡动画,需要指定动画连接的源图片元素。
已尝试方案
在GridView的项点击处理程序中编写了以下代码,但无法访问目标图片元素:
ConnectedAnimationService.GetForCurrentView() .PrepareToAnimate("forwardAnimation", ImageBoxMain);
遇到的问题
ImageBoxMain位于DataTemplate内部,无法在后台代码直接访问,报错:The type or namespace name 'ImageBoxMain' could not be found,无法获取ConnectedAnimation所需的UIElement类型的源图片。
解决方案
由于DataTemplate内的元素属于项容器的子元素,需通过视觉树遍历获取目标控件,具体步骤如下:
- 在
ItemClick事件中,先获取点击的数据项对应的GridViewItem容器; - 遍历容器的视觉树,找到名为
ImageBoxMain的Image控件; - 将找到的控件传入
ConnectedAnimation的准备方法。
完整代码示例
private void ImageListBox_ItemClick(object sender, ItemClickEventArgs e) { // 获取点击的数据项 var clickedImage = e.ClickedItem as DisplayedImage; if (clickedImage == null) return; // 获取对应项的GridViewItem容器 var gridViewItem = ImageListBox.ContainerFromItem(clickedImage) as GridViewItem; if (gridViewItem == null) return; // 遍历视觉树查找目标Image控件 var sourceImage = FindVisualChild<Image>(gridViewItem, "ImageBoxMain"); if (sourceImage != null) { // 准备连接动画 ConnectedAnimationService.GetForCurrentView() .PrepareToAnimate("forwardAnimation", sourceImage); // 执行页面导航(示例) Frame.Navigate(typeof(ImageDetailPage), clickedImage); } } // 辅助方法:递归遍历视觉树,查找指定名称的目标控件 private T FindVisualChild<T>(DependencyObject parent, string targetName) where T : FrameworkElement { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var child = VisualTreeHelper.GetChild(parent, i); if (child is T typedChild && typedChild.Name == targetName) { return typedChild; } var foundChild = FindVisualChild<T>(child, targetName); if (foundChild != null) { return foundChild; } } return null; }
补充说明
- 若希望简化查找逻辑,也可以给
Image控件设置x:FieldModifier="public",不过这种方式在项频繁刷新时可能出现控件引用失效的问题,视觉树遍历的方式更稳定通用; - 在详情页中,需要调用
ConnectedAnimationService.GetForCurrentView().GetAnimation("forwardAnimation")?.TryStart(targetImage)来启动动画,确保目标图片的名称和动画标识匹配。
内容的提问来源于stack exchange,提问作者Wind_Explorer
相关产品推荐
相关产品推荐

