Overlapping Items in WPF ItemsControl

4.8k views Asked by At

I am having a problem with DataTemplates used in a WPF ItemsControl. I want to be able to "bring forward" any of the items in the list so that they are on top of everything else in the list, but haven't had any luck.

Here's a simple example that illustrates the problem. What I want to see is achieved in the example using a WrapPanel and a bunch of colored blocks:

enter image description here

The first block overlaps the second. Good. When I try to do the same thing with the ItemsControl, the first block falls underneath the second, despite its ZIndex:

enter image description here

How can I make the first block overlap all the others in the ItemsControl?

From my understanding of the ZIndex property, I am assuming that I need to set the ZIndex higher up in the Visual Tree than the Border inside of the DataTemplate, but don't know how or where to do that.

XAML:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:MainViewModel x:Key="mainViewModel" />
    <DataTemplate DataType="{x:Type local:FireFighter}">
        <Border Background="Pink" Padding="8" Panel.ZIndex="10" Margin="4">
            <Border.RenderTransform>
                <TranslateTransform X="18" Y="4"/>
            </Border.RenderTransform>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </Border>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:PoliceOfficer}">
        <Border Background="Orange" Padding="8" Margin="4">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </Border>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <ItemsControl DataContext="{StaticResource mainViewModel}" 
              ItemsSource="{Binding People}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
    <WrapPanel Margin="0,10,0,0">
        <Border Background="Blue" Width="30" Height="30" Margin="4" Panel.ZIndex="10">
            <Border.RenderTransform>
                <TranslateTransform X="18" Y="4"/>
            </Border.RenderTransform>
        </Border>
        <Border Background="Green" Width="30" Height="30" Margin="4"/>
        <Border Background="Green" Width="30" Height="30" Margin="4"/>
    </WrapPanel>
</StackPanel>

2

There are 2 answers

0
CrumblyRock On BEST ANSWER

I found an answer that will work for my situation right here:

https://stackoverflow.com/a/9687758/4912801

It turns out that setting the Panel.ZIndex property wasn't working because WPF inserts a ContentPresenter element for each item in the ItemsControl. In my application, I was trying to get whatever element the mouse is hovering over to come to the front, so applying a style to all ContentPresenters in the ItemsControl allowed me to bring them to the front when the mouse was over them.

0
NielW On

I was looking for something similar and this is what did it for me. Use a UniformGrid as your ItemsPanelTemplate, then change the margins on your DataTemplate to overlap as much as you want.

    <Grid Grid.Row="1"
           Grid.ColumnSpan="2">
        <Grid.Resources>
            <local:PointsToPathConverter x:Key="pointsToPathConverter"/>
        </Grid.Resources>
        <Image 
           Source="{Binding Bmp}"
           Stretch="Fill"
           VerticalAlignment="Stretch"
           HorizontalAlignment="Stretch" />
        <ItemsControl ItemsSource="{Binding AllTraceLines}" 
                      VerticalAlignment="Stretch" 
                      >
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="1"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Path Margin="0,-20,0,-20"  Data="{Binding Converter={StaticResource pointsToPathConverter}}" Stroke="Red" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="Fill"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>