Richard
Richard

Reputation: 30618

Setting Z-Index in DataBound items on a Canvas

I am trying to bind a list of items to an ItemsControl, using a Canvas layout, where the item has multiple "levels". This is easiest to explain using an image:

Problem

My lower level is a drop-shadow in this case. Because I assumed the drop shadow would be attached to the main element (a Button), I created another visual element, a Border, which sits behind the Button and has the shadow attached. What I would like is for all of my shadow elements to be at the same overall ZIndex, and all of the Button elements to be above them.

In practice, it appears that WPF renders the contents of my template as a single UI element, essentially flattening the ZIndexes within it. Is there any way I can make it so that the ZIndex values are not flattened?

I have created a sample below which shows the problem:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="600" Background="White">
  <Window.Resources>
    <DropShadowEffect Color="Blue" BlurRadius="75" x:Key="ActionDropShadow" />

    <XmlDataProvider x:Key="myData" XPath="Data/Items">
      <x:XData>
        <Data xmlns="">
          <Items>
            <Item X="50" Title="AAA" />
            <Item X="100" Title="BBB" />
            <Item X="150" Title="CCC" />
          </Items>
        </Data>
      </x:XData>
    </XmlDataProvider>

    <DataTemplate x:Key="BoxTemplate">
      <Grid>
        <Border Background="Black" BorderThickness="1"  Effect="{StaticResource ActionDropShadow}" />
        <Button Background="White" BorderThickness="1">
          <TextBlock Text="{Binding XPath=@Title}" />
        </Button>
      </Grid>
    </DataTemplate>
  </Window.Resources>

  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <ItemsControl Grid.Column="0" x:Name="list" ItemTemplate="{StaticResource BoxTemplate}" ItemsSource="{Binding Source={StaticResource myData},XPath=*}">
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <Canvas />
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
      <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
          <Setter Property="Canvas.Left" Value="{Binding XPath=@X}" />
          <Setter Property="Canvas.Top" Value="50" />
          <Setter Property="Width" Value="50" />
          <Setter Property="Height" Value="80" />
        </Style>
      </ItemsControl.ItemContainerStyle>
    </ItemsControl>

    <Canvas Grid.Column="1">
      <Border Panel.ZIndex="5" Canvas.Top="50" Canvas.Left="50" Width="50" Height="80" Background="Black" BorderThickness="1"  Effect="{StaticResource ActionDropShadow}"  />
      <Button Panel.ZIndex="10" Canvas.Top="50" Canvas.Left="50" Width="50" Height="80" Background="White" BorderThickness="1">
        <TextBlock Text="AAA" />
      </Button>
      <Border Panel.ZIndex="5" Canvas.Top="50" Canvas.Left="100" Width="50" Height="80" Background="Black" BorderThickness="1"  Effect="{StaticResource ActionDropShadow}" />
      <Button Panel.ZIndex="10" Canvas.Top="50" Canvas.Left="100" Width="50" Height="80" Background="White" BorderThickness="1">
        <TextBlock Text="BBB" />
      </Button>
      <Border Panel.ZIndex="5" Canvas.Top="50" Canvas.Left="150" Width="50" Height="80" Background="Black" BorderThickness="1"  Effect="{StaticResource ActionDropShadow}" />
      <Button Panel.ZIndex="10" Canvas.Top="50" Canvas.Left="150" Width="50" Height="80" Background="White" BorderThickness="1">
        <TextBlock Text="CCC" />
      </Button>
    </Canvas>

    <TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center">Databinding Version</TextBlock>
    <TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center">What it should look like</TextBlock>
  </Grid>
</Window>

Thanks in advance for any ideas you can offer!

Upvotes: 2

Views: 2064

Answers (2)

brunnerh
brunnerh

Reputation: 184286

Since the bound objects are wrapped in a ContentPresenter all internal ZIndex settings will be ignored, so you cannot do what you described. You might be better off creating an ItemsControl for each layer.

Upvotes: 3

Mo0gles
Mo0gles

Reputation: 10884

Get the parent ContentPresenter and set ZIndex on that.

E.g:

var parent = (UIElement) VisualTreeHelper.GetParent((UIElement) sender);
parent.SetZIndex(parent, z);

Upvotes: 0

Related Questions