uwp GridView selectedItem 弹出窗口

Posted

技术标签:

【中文标题】uwp GridView selectedItem 弹出窗口【英文标题】:uwp GridView selectedItem Popup 【发布时间】:2018-08-09 12:16:05 【问题描述】:

我正在使用 UWP 社区工具包的 AdaptiveGridView。我希望 gridview 的所选项目 在 Z 轴上弹出,这意味着所选项目必须放大到特定大小,但它不应该干扰其他 gridview 项目的大小,而是应该在画布的 Z 轴 上缩放。使用 UWP 社区工具包 scale effect 制作这种效果的可能性有哪些(但这也会影响其他项目的大小)。如果在选定的项目上不可能,在指针悬停时是否有可能?

【问题讨论】:

您尝试了哪种缩放方法?通常,比例更改不会影响布局,但大小更改会。 @JustinXL 我正在尝试解决这个问题。我使用var container = AdaptiveGridViewControl.ContainerFromIndex(AdaptiveGridViewControl.SelectedIndex) as FrameworkElement 获取所选项目的容器,并尝试使用container.Scale(2, 2, 0, 0, 500, 0, EasingType.Default) 增加比例,但它不会增加比例,但是当我更改宽度(或高度)时,它会按预期影响所选项目。为什么缩放不影响布局? 它最有可能不会改变比例,因为每个gridview项目都在一定的边界内。 对不起,我的意思是尺寸变化,这会影响布局,正如@VijayNirmal 测试的那样,由于边界,缩放不会对项目造成任何影响,我们需要一种绕过边界的方法也许在 Z 轴上? @JustinXL 那么改变宽度(或高度)如何影响所选项目? 【参考方案1】:

方法 1:选择时更改

XAML 部分

<GridView Height="200" SelectionChanged="GridView_SelectionChanged">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="local:ItemSource">
            <Grid Width="100" Height="100">
                <!-- Content -->
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
</GridView>

C#部分

FrameworkElement lastPopUpElement = null;
private void GridView_SelectionChanged(object sender, SelectionChangedEventArgs e)

    if (lastPopUpElement != null)
    
        Canvas.SetZIndex(lastPopUpElement, 0);
        lastPopUpElement.Scale(centerX: 50, centerY: 50, easingType: EasingType.Sine).Start();
    

    lastPopUpElement = (sender as GridView).ContainerFromIndex((sender as GridView).SelectedIndex) as FrameworkElement;

    if (lastPopUpElement != null)
    
        Canvas.SetZIndex(lastPopUpElement, 1);
        lastPopUpElement.Scale(scaleX: 1.5f, scaleY: 1.5f, centerX: 50, centerY: 50, easingType: EasingType.Sine).Start();
    

样本输出

方法二:指针悬停

XAML 部分

<GridView Height="200">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="local:ItemSource">
            <Grid Width="100" Height="100" PointerEntered="GridView_PointerEntered" PointerExited="GridView_PointerExited">
                <!-- Content -->
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
</GridView>

C#部分

FrameworkElement lastPopUpElement = null;
private void GridView_PointerEntered(object sender, PointerRoutedEventArgs e)

    lastPopUpElement = VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(sender as FrameworkElement) as FrameworkElement) as FrameworkElement;
    Canvas.SetZIndex(lastPopUpElement, 1);
    lastPopUpElement.Scale(scaleX: 1.5f, scaleY: 1.5f, centerX: 50, centerY: 50, easingType: EasingType.Sine).Start();


private void GridView_PointerExited(object sender, PointerRoutedEventArgs e)

    if (lastPopUpElement != null)
    
        Canvas.SetZIndex(lastPopUpElement, 0);
        lastPopUpElement.Scale(centerX: 50, centerY: 50, easingType: EasingType.Sine).Start();
    

样本输出

方法 3:使用投影

XAML 部分

<GridView Height="200">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="local:ItemSource">
            <controls:DropShadowPanel OffsetX="5" OffsetY="5" Color="Black" BlurRadius="5" ShadowOpacity="0" PointerEntered="myListView_PointerEntered" PointerExited="myListView_PointerExited">
                <Grid Width="100" Height="100" VerticalAlignment="Center" HorizontalAlignment="Center">
                    <!-- Content -->
                </Grid>
            </controls:DropShadowPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
</GridView>

C#部分

private void myListView_PointerEntered(object sender, PointerRoutedEventArgs e)

    DropShadowPanel DropShadow = sender as DropShadowPanel;
    lastPopUpElement = VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(DropShadow) as FrameworkElement) as FrameworkElement;
    DropShadow.ShadowOpacity = 0.5;
    Canvas.SetZIndex(lastPopUpElement, 10);
    lastPopUpElement.Scale(scaleX: 1.5f, scaleY: 1.5f, centerX: 50, centerY: 50, easingType: EasingType.Sine).Start();


private void myListView_PointerExited(object sender, PointerRoutedEventArgs e)

    if (lastPopUpElement != null)
    
        DropShadowPanel DropShadow = sender as DropShadowPanel;
        DropShadow.ShadowOpacity = 0;
        Canvas.SetZIndex(lastPopUpElement, 0);
        lastPopUpElement.Scale(centerX: 50, centerY: 50, easingType: EasingType.Sine).Start();
    

样本输出


(旧帖)

方法一(不与其他物品叠加)

XAML 部分

<Grid Name="MainGrid" Height="200">
    <controls:AdaptiveGridView x:Name="myAdaptiveGridView" SelectionChanged="myAdaptiveGridView_SelectionChanged" VerticalAlignment="Center" HorizontalAlignment="Left">
        <controls:AdaptiveGridView.ItemTemplate>
            <DataTemplate>
                <Grid Width="150" Height="150">
                    <Grid Width="100" Height="100" VerticalAlignment="Center" HorizontalAlignment="Center">
                        <!-- Content -->
                    </Grid>
                </Grid>
            </DataTemplate>
        </controls:AdaptiveGridView.ItemTemplate>
    </controls:AdaptiveGridView>
</Grid>

C#部分

FrameworkElement oldSetectedItem = null;

private void myAdaptiveGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)

    if (oldSetectedItem != null)
        oldSetectedItem.Scale(1, 1, 50, 50, 500).Start();

    var container = myAdaptiveGridView.ContainerFromIndex(myAdaptiveGridView.SelectedIndex) as FrameworkElement;
    var listViewItemPresenter = VisualTreeHelper.GetChild(container, 0) as FrameworkElement;
    var outerGrid = VisualTreeHelper.GetChild(listViewItemPresenter, 0) as FrameworkElement;
    var grid = VisualTreeHelper.GetChild(outerGrid, 0) as FrameworkElement;
    oldSetectedItem = grid;

    grid.Scale(1.5f, 1.5f, 50, 50, 500).Start();

样本输出

方法二(会与其他物品叠加)

XAML 部分

<Grid Name="MainGrid" Height="200">
    <controls:AdaptiveGridView x:Name="myAdaptiveGridView" SelectionChanged="myAdaptiveGridView_SelectionChanged" VerticalAlignment="Center" HorizontalAlignment="Left">
        <controls:AdaptiveGridView.ItemTemplate>
            <DataTemplate>
                <Grid Width="100" Height="100" VerticalAlignment="Center" HorizontalAlignment="Center">
                    <!-- Content -->
                </Grid>
            </DataTemplate>
        </controls:AdaptiveGridView.ItemTemplate>
    </controls:AdaptiveGridView>
    <Image x:Name="RenderedImage" Stretch="None" Visibility="Collapsed" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>

C#部分

private async void myAdaptiveGridView_SelectionChangedAsync(object sender, SelectionChangedEventArgs e)

    RenderedImage.Scale(1, 1, 0, 0, 0).Start();

    var container = myAdaptiveGridView.ContainerFromIndex(myAdaptiveGridView.SelectedIndex) as FrameworkElement;
    var listViewItemPresenter = VisualTreeHelper.GetChild(container, 0) as FrameworkElement;
    var grid = VisualTreeHelper.GetChild(listViewItemPresenter, 0) as FrameworkElement;
    oldSetectedItem = grid;

    var TTV = grid.TransformToVisual(MainGrid);
    Point screenCoords = TTV.TransformPoint(new Point(0, 0));

    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(grid);
    RenderedImage.Source = renderTargetBitmap;
    RenderedImage.Margin = new Thickness(screenCoords.X, screenCoords.Y, 0, 0);
    RenderedImage.Width = grid.ActualWidth;
    RenderedImage.Height = grid.ActualHeight;
    RenderedImage.Visibility = Visibility.Visible;

    RenderedImage.Scale(1.5f, 1.5f, 50, 50, 500).Start();

样本输出

【讨论】:

这是一个绝妙的答案,干得好@VijayNirmal 我认为我们还可以添加阴影效果,这将改善叠加效果,但您已经完成了核心任务,非常感谢 :) 顺便说一下在第二种方法中,为什么你把外网格的高度设置为150?我猜它也可以使用 100 高度,因为它应该覆盖 @JustinXL 谢谢 @touseef 是的。你可以删除它。我将编辑我的答案。 我在 UWPCommunityToolkit 中打开了一个issue 来创建一个弹出动画。

以上是关于uwp GridView selectedItem 弹出窗口的主要内容,如果未能解决你的问题,请参考以下文章

UWP 组合框绑定到 SelectedItem 属性

Windows 10 UWP - 不可见时没有 DataContext 的 GridView 项目

UWP GridView切换数据时界面闪动

uwp 自适应 gridview 渲染第一个元素错误

uwp gridview项目源甚至没有执行

Windows UWP - 如何将 GridView 包装在 HubSection 中