2009-03-10 8 views
36

Tutta la documentazione e gli esempi che sto trovando online per impostare Z-Index per portare un elemento in avanti in Silverlight utilizzano un elemento Canvas come contenitore.Porta avanti l'elemento (Indice Z) in Silverlight/WPF

I miei elementi sono elementi di bordo all'interno di un contenitore ItemsControl in un DataTemplate. Sto utilizzando gli eventi MouseEnter e MouseLeave per attivare un'animazione su ScaleTransform.ScaleX e ScaleTransform.ScaleY in modo che crescano quando ci si alza. Quando vengono ridimensionati e occupano lo stesso spazio degli altri oggetti nel (i) contenitore (i), gli elementi aggiunti più recentemente si sovrappongono agli elementi precedenti (in contrasto con l'elemento attualmente ridimensionato). C'è un modo PULITO per far avanzare l'elemento corrente nel codice in cui attingo la mia animazione in modo che si sovrappongano a tutti gli altri oggetti quando vengono ridimensionati?

risposta

2

Innanzitutto, la proprietà associata Zindex è definita in Canvas e pertanto non è disponibile in altri derivati ​​di Parallels Panel.

Il ItemsControl ordina i sottoelementi in base all'ordine della lista. Il primo oggetto in fondo alla pila e l'ultimo in cima. Con quello dato, tutto ciò che devi fare è assicurarti che l'elemento selezionato sia in fondo alla lista.

Prima creare un'interfaccia per l'ordine. In questo modo:

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

Ora implementalo nella classe che stai visualizzando.

Quando si desidera portare un oggetto in primo piano, dargli un numero elevato e dare a tutti gli altri un numero basso.

Al è rimasto l'ordine attuale. Aggiungere qualcosa di simile e siete a posto:

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

ho pensato che in un primo momento, ma in modo che gli elementi per sovrappongono, avevano tutti devono essere figli di una grande tela. Non mi aspetto che uno z-index in una tela abbia un effetto sull'indice z di un altro. Ma se uso una grande tela, gli elementi non ne sono comunque figli diretti – Rich

+0

In realtà, ZIndex funziona per altri tipi di Pannello. Vai avanti e provalo. – ptoinson

15

In WPF v'è la proprietà Panel.ZIndex che è possibile impostare in un trigger:

<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> 

Nel Style per ContentPresenter abbiamo impostato il Panel.ZIndex-99.999 quando IsMouseOver è true. Deve essere il ContentPresenter e non loperché gli ContentPresenter sono figli del pannello di ItemsControl.

Purtroppo non credo che questa proprietà ha reso a Silverlight ancora ...

+0

Sì ... L'ho visto anche io e sto usando ItemsControl come contenitore che deriva da Panel, ma l'oggetto non è disponibile in SL. Thx – Rich

+3

Bella risposta-- questo mi ha aiutato un po '. – Charlie

34

che ho avuto a che fare con questo.

Si supponga di disporre di un ItemControl con un ItemTemplate impostato su un'istanza di un controllo personalizzato. All'interno di quel controllo fai Canvas.SetZIndex (questo, 99). Non funzionerà, perché "questo" non è il figlio immediato di ItemsPanel di ItemsControl. ItemsControl crea un ContentPresenter per ciascun elemento, lo elimina nel ItemsPanel e esegue il rendering del ItemTemplate all'interno di ContentPresenter.

Quindi, se si desidera modificare ZIndex nel proprio controllo, è necessario trovare il relativo ContentPresenter e modificare ZIndex su quello. Un modo è ...

 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

Oltre agli errori di sintassi, questo funziona. Ho provato a impostare lo ZIndex da Silverlight Spy 3 (che ho provato a ispezionare tutto), ma a quanto pare non imposta ZIndex (continua a tornare a 0). Trovare il ContentPresenter usando questo helper ha fatto il trucco. –

+0

Leggendario, questo ha fatto il trucco per i miei problemi di stratificazione delle finestre. –

+0

Ha lavorato su questo per giorni prima di trovare questo post. A differenza di Bart, il codice ha funzionato più o meno come lo è per me. PS: È possibile modificare la funzione FindVisualParent in una funzione normale, se non si desidera utilizzare i metodi di estensione, modificando il suo prototipo di funzione in "public static T FindVisualParent (DependencyObject obj) dove T: DependencyObject" Viene quindi richiamato il nuovo metodo chiamando ContentPresenter foo = this.FindVisualParent (this); –

2

Html funziona allo stesso modo. Tutte le voci dell'elenco devono essere fratelli se si desidera disporli a strati.

Ho esteso il codice sopra in modo che si fermi se trova (ad esempio) un oggetto ItemsPresenter.Se ContentPresenter non viene mostrato tra qui e ItemsPresenter, ripiega sul mio codice originale.

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

Per un controllo che utilizza la rete come LayoutRoot si può semplicemente fare qualcosa di semplice come quella all'interno di un controllo stesso:

Canvas.SetZIndex(this, 999); 
1

impostare zIndex del vostro elemento in questo modo

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

zIndex++; 

Canvas.SetZIndex(element, zIndex); 
  • forse è necessario verificare se zIndex è uguale a int.MaxValue quindi ripristinare "ZIndex" s.
  • ma questo non accade quasi mai
3

prima trovare lo ZIndex massima di tutti i suoi elementi figlio e quindi impostare il nuovo 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; 
} 

quindi assegnare

Canvas.SetZIndex(child, MaxZIndex());