2009-03-10 9 views
36

Toda la documentación y los ejemplos que encuentro en línea para configurar Z-Index para llevar un elemento adelante en Silverlight están utilizando un elemento Canvas como contenedor.Llevar elemento hacia adelante (índice Z) en Silverlight/WPF

Mis elementos son elementos del borde dentro de un contenedor ItemsControl en un DataTemplate. Estoy usando los eventos MouseEnter y MouseLeave para activar una animación en ScaleTransform.ScaleX y ScaleTransform.ScaleY para que crezcan cuando se ciernen. A medida que se cambian de tamaño y ocupan el mismo espacio que otros elementos en el contenedor (es), los elementos añadidos más recientemente se superponen a los elementos más antiguos (a diferencia del elemento de cambio de tamaño actual). ¿Hay alguna forma LIMPIA de reenviar el elemento actual en el código donde desencadené mi animación para que se superpongan a todos los demás elementos cuando se cambian de tamaño?

Respuesta

2

En primer lugar, la propiedad adjunta Zindex se define en Canvas y, por lo tanto, no está disponible en otros derivados del Panel.

ItemsControl ordena los subelementos según el orden de la lista. El primer elemento en la parte inferior de la pila y el último en la parte superior. Con eso dado, todo lo que tiene que hacer es asegurarse de que el elemento seleccionado esté en la parte inferior de la lista.

Primero cree una interfaz para el pedido. De esta manera:

interface IOrderable 
    { 
     int theZOrder{get;set;} 
    } 

Ahora implemente esto en la clase que está mostrando.

Cuando quiera llevar un artículo al frente, dele un número alto y dé a todos los demás un número bajo.

Al que queda es el orden real. Añadir algo como esto y ya está listo:

ItemsCont.ItemsSource = 
      ItemsCont.Items.OrderByDesc(t=>((IOrderable)t).theZOrder); 
+0

me había ocurrido al principio, pero a fin de que los elementos que se solapan entre sí, que todos tendríamos que ser hijos de un gran lienzo. No esperaría que un índice z en un lienzo tenga un efecto en el índice Z de otro. Pero si utilizo un lienzo grande, los elementos no son hijos directos de todos modos – Rich

+0

En realidad, ZIndex funciona para otros tipos de paneles. Sigue adelante e inténtalo. – ptoinson

15

En WPF no es la propiedad Panel.ZIndex que se puede establecer en un disparador:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Grid.Resources> 
     <x:Array x:Key="colors" Type="{x:Type Color}"> 
      <Color>Green</Color> 
      <Color>Red</Color> 
      <Color>Blue</Color> 
      <Color>Orange</Color> 
      <Color>Yellow</Color> 
      <Color>Violet</Color> 
     </x:Array> 
     <DataTemplate DataType="{x:Type Color}"> 
      <Border x:Name="brd" Height="20" Width="20"> 
       <Border.Background> 
        <SolidColorBrush Color="{Binding}"/> 
       </Border.Background> 
       <Border.RenderTransform> 
        <ScaleTransform CenterX="10" CenterY="10"/> 
       </Border.RenderTransform> 
       <Border.Style> 
        <Style TargetType="{x:Type Border}"> 
         <Style.Triggers> 
          <Trigger Property="IsMouseOver" Value="True"> 
           <Setter Property="BorderThickness" Value="2"/> 
           <Setter Property="BorderBrush" Value="Black"/> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </Border.Style> 
       <Border.Triggers> 
        <EventTrigger RoutedEvent="Border.MouseEnter"> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetName="brd" Storyboard.TargetProperty="RenderTransform.ScaleX" To="1.5"/> 
           <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetName="brd" Storyboard.TargetProperty="RenderTransform.ScaleY" To="1.5"/> 
          </Storyboard> 
         </BeginStoryboard> 
        </EventTrigger> 
        <EventTrigger RoutedEvent="Border.MouseLeave"> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetName="brd" Storyboard.TargetProperty="RenderTransform.ScaleX" To="1"/> 
           <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetName="brd" Storyboard.TargetProperty="RenderTransform.ScaleY" To="1"/> 
          </Storyboard> 
         </BeginStoryboard> 
        </EventTrigger> 
       </Border.Triggers> 
      </Border> 
     </DataTemplate> 
    <Style TargetType="{x:Type ContentPresenter}"> 
     <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="True"> 
       <Setter Property="Panel.ZIndex" Value="99999"/> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
    </Grid.Resources> 
    <ItemsControl ItemsSource="{StaticResource colors}" Margin="20" Width="40"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</Grid> 

En el Style para ContentPresenter nos fijamos el Panel.ZIndex-99.999 cuando IsMouseOver es true. Debe estar en el ContentPresenter y no en el Border porque los ContentPresenter s son hijos del panel ItemsControl.

Por desgracia no creo que esta propiedad ha llegado a Silverlight sin embargo ...

+0

Sí ... lo vi también, y estoy usando ItemsControl como mi contenedor que se deriva del Panel, pero el accesorio no está disponible en SL. Thx – Rich

+3

Buena respuesta-- esto me ayudó bastante. – Charlie

34

que he tenido que hacer frente a esto.

Supongamos que tiene un ItemsControl con un ItemTemplate establecido en una instancia de un control personalizado. Dentro de ese control, usted hace Canvas.SetZIndex (esto, 99). No funcionará, porque "este" no es el elemento secundario del Panel de elementos de ItemsControl. ItemsControl crea un ContentPresenter para cada elemento, lo coloca en el Panel de elementos y representa ItemTemplate en ContentPresenter.

Por lo tanto, si desea cambiar el ZIndex dentro de su control, debe encontrar su ContentPresenter y cambiar el ZIndex sobre eso. Una forma es ...

 public static T FindVisualParent<T>(this DependencyObject obj) 
     where T : DependencyObject 
    { 
     DependencyObject parent = VisualTreeHelper.GetParent(obj); 
     while (parent != null) 
     { 
      T typed = parent as T; 
      if (typed != null) 
      { 
       return typed; 
      } 
      parent = VisualTreeHelper.GetParent(parent); 
     } 
     return null; 
    } 
       ContentPresenter foo = this.FindVisualParent<ContentPresenter>(); 
      Canvas.SetZIndex(foo, 99); 
+0

Además de los errores de sintaxis, esto funciona. Intenté configurar el ZIndex de Silverlight Spy 3 (que traté de inspeccionar todo esto), pero aparentemente no configura el ZIndex (vuelve a 0). Encontrar el ContentPresenter usando esta ayuda hizo el truco. –

+0

Legendario, este fue el truco para mis problemas de capas de ventanas. –

+0

Ha trabajado en esto durante días antes de encontrar esta publicación. A diferencia de Bart, el código funcionó bastante bien para mí. PS: Puede cambiar la función FindVisualParent a una función normal, si no desea usar métodos de extensión, cambiando su prototipo de función a "static T local FindVisualParent (DependencyObject obj) donde T: DependencyObject" A continuación, invoque el nuevo método llamando a ContentPresenter foo = this.FindVisualParent (this); –

2

Html funciona de la misma manera. Todos los elementos de la lista deben ser hermanos si desea colocarlos en capas.

He extendido el código anterior para que se detenga si encuentra (por ejemplo) un ItemsPresenter.Si el ContentPresenter no se muestra entre aquí y el ItemsPresenter, entonces recurra a mi código original.

void setZindex(MyLayeredType layeredObj, int index) 
{ 
    ContentPresenter sibbling = 
    FindVisualParent<ContentPresenter, ItemsPresenter>(layeredObj); 
    if (sibbling != null) 
    { 
     sibbling.SetValue(Canvas.ZIndexProperty, index); 
    } 
    else 
    { 
     layeredObj.SetValue(Canvas.ZIndexProperty, index); 
    } 
} 

public static T FindVisualParent<T,C>(this DependencyObject obj) 
where T : DependencyObject 
where C : DependencyObject 
{ 
    DependencyObject parent = VisualTreeHelper.GetParent(obj); 
    while (parent != null) 
    { 
     T typed = parent as T; 
     if (typed != null) 
     { 
      return typed; 
     } 
     C ceiling = parent as C; 
     if (ceiling != null) 
      return null; 
     parent = VisualTreeHelper.GetParent(parent); 
    } 
    return null; 
} 
3

Para un control que utiliza la red como LayoutRoot que sólo puede hacer algo tan simple como que dentro de un control de sí mismo:

Canvas.SetZIndex(this, 999); 
1

establecer zIndex de su elemento de esta manera

var zIndex = 
    ((Panel) element.Parent) 
    .Children.Cast<UIElement>() 
    .Max(child => Canvas.GetZIndex(child)) 
    ; 

zIndex++; 

Canvas.SetZIndex(element, zIndex); 
  • quizás necesite comprobar si zIndex es igual a int.MaxValue luego restablecer "ZIndex" s.
  • pero esto casi nunca sucede
3

En primer lugar encontrar el máximo ZIndex de todos sus elementos secundarios y luego establecer el nuevo ZIndex.

private int MaxZIndex() 
{ 
    int iMax = 0; 
    foreach (UIElement element in JIMSCanvas.Children) 
    {    
     int iZIndex=Canvas.GetZIndex(element); 
     if(iZIndex>iMax) 
     { 
      iMax = iZIndex; 
     } 
    } 
    return iMax+1; 
} 

luego asignar

Canvas.SetZIndex(child, MaxZIndex()); 
Cuestiones relacionadas