在鼠标输入或拖动完成时锁定 ContentPresenter 的 zIndex

Lock zIndex of a ContentPresenter Upon Mouse Enter or Drag Complete

我需要在 canvas/content 控件被 Thumb 拖动后锁定它的 Z 顺序。

在下图中,当鼠标悬停处于活动状态时,"Joe Smith" 在其他两个椭圆上方弹出。一旦拖动停止并且鼠标移出,它就会回到它的值。

我无法在下面显示的设计中找到解决方案,以将其锁定在其他设计之上。


最小可重现示例

我创建了包含 xaml、拇指 class 和人员 class 的所有代码的 code gist。所要做的就是创建一个 .Net Core WPF 应用程序并放入代码片段并根据需要在 Xaml 中设置名称间距。


设计 有一个 ItemsControl,其中 DataTemplate 定义为 CanvasItemsControl 中的每个内容都有 ContentControl,其中有一个 Thumb 被样式应用。

鼠标进入 ContentPresenter 的另一种样式触发器通过设置内容的内部 [=20] 将内容 临时 推入 zIndex 高于其他内容=] 的 zIndex 到 1.

如何粘贴那个zIndex

Xaml

<ItemsControl Margin="10" ItemsSource="{Binding Source={StaticResource People}}">

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="1" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Canvas>
                <ContentControl  Width="100" Height="100" >
                    <Grid>
                        <Ellipse Fill="Silver">
                            <Ellipse.Effect>
                                <DropShadowEffect Color="Black" Direction="320"  ShadowDepth="6"  Opacity="0.5"/>
                            </Ellipse.Effect>
                        </Ellipse>
                        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                            <TextBlock Margin="3,3,3,0" Text="{Binding Path=First}"/>
                            <TextBlock Margin="3,0,3,7" Text="{Binding Path=Last}"/>
                        </StackPanel>
                    </Grid>
                </ContentControl>
            </Canvas>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="{x:Type ContentPresenter}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Grid.ZIndex" Value="1"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

查看 Gist 以了解所有支持的 classes 和样式以重现


实际设计

最终目标是拥有一个固定大小的图像面板,当用户抓住拇指时,图像将向前移动并锁定在其他图像之上。我这样说是为了防止有另一种方法可以在最小示例设计之上提供答案。

在我的 ItemsControl 中,我将 ItemsPanelTemplate 更改为 Canvas 例如

<ItemsPanelTemplate>
    <Canvas x:Name="MainCanvas" />
</ItemsPanelTemplate>

当查看用户单击 ContentControl 的可视化树时,它有一个 Canvas 的父级,该 ContentPresenter 具有顶级 [=15] =] 例如(见命名MainCanvas):

我将 ContentControl 更改为有一个 MouseEnter 事件:

<ContentControl  Width="100" Height="100" MouseEnter="EnterMouse">
   <Grid>
       <Ellipse Fill="Silver">

在该方法中,我需要找到命名的 "MainCanvas" Canvas 并枚举其所有子项 ContentPresenter 并提取最大 ZIndex,然后设置我的 ContentControl(如上图蓝色所示)到 ZIndex 值加 1。

下面是提取必要父项的代码:

private void EnterMouse(object sender, MouseEventArgs e)
{
    if (sender is ContentControl cc)
    {
        var cpParent = FindParent<ContentPresenter>(cc);
        var p2 = FindParent<Canvas>(cpParent);

        var max = p2.Children.Cast<UIElement>().Max(control => Panel.GetZIndex(control));
        Panel.SetZIndex(cpParent, max + 1);
    }
}

private T FindParent<T>(DependencyObject child) where T : DependencyObject
{
    DependencyObject immediateParent = VisualTreeHelper.GetParent(child);

    T parent = immediateParent as T;

    return parent ?? FindParent<T>(immediateParent);
}