Bring element forward (Z Index) in Silverlight/WPF

前端 未结 7 1623
有刺的猬
有刺的猬 2020-12-04 19:42

All the documentation and examples I\'m finding online for setting Z-Index to bring an element forward in Silverlight are using a Canvas element as a container.

My i

相关标签:
7条回答
  • 2020-12-04 19:59

    Html works the same way. All the list items must be siblings if you want to lay them out in layers.

    I extended the code above so that it will stop if it finds (for example) an ItemsPresenter. If the ContentPresenter doesn't show itself between here and the ItemsPresenter, then fall back on my original code.

    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;
    }
    
    0 讨论(0)
  • 2020-12-04 20:09

    For a control that uses the Grid as LayoutRoot you can just do something as simple as that within a control itself:

    Canvas.SetZIndex(this, 999);
    
    0 讨论(0)
  • 2020-12-04 20:12

    I've had to deal with this.

    Say you have an ItemsControl with an ItemTemplate set to an instance of a custom control. Within that control you do Canvas.SetZIndex(this, 99). It won't work, because "this" is not the immediate child of the ItemsControl's ItemsPanel. The ItemsControl creates a ContentPresenter for each item, drops that into the ItemsPanel, and renders the ItemTemplate within the ContentPresenter.

    So, if you want to change the ZIndex within your control, you have to find its ContentPresenter, and change the ZIndex on that. One way is...

            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 讨论(0)
  • 2020-12-04 20:12

    First find the Maximum ZIndex of all its child elements and then set the new 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;
    }
    

    Then assign

    Canvas.SetZIndex(child, MaxZIndex());
    
    0 讨论(0)
  • 2020-12-04 20:13

    In WPF there is the Panel.ZIndex property that you can set in a 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>
    

    In the Style for ContentPresenter we set the Panel.ZIndex to 99999 when IsMouseOver is true. It must be on the ContentPresenter and not the Border because the ContentPresenters are children of the ItemsControl's panel.

    Unfortunately I don't think this property has made it to Silverlight yet...

    0 讨论(0)
  • 2020-12-04 20:16

    First, the attached property Zindex is defined in Canvas and thus is not available in other derivatives of Panel.

    The ItemsControl orders the subelements according to the order of the list. The first Item at the bottom of the stack and the last on top. With that given, all you have to do is making sure the selected item is on bottom of the list.

    First create an interface for the ordering. Like this:

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

    Now implement this in the class you're showing.

    When you want to bring a item to the front, give it a high number and give all others a low number.

    Al there's left is the actual ordering. Add something like this and you're set:

    ItemsCont.ItemsSource = 
                ItemsCont.Items.OrderByDesc(t=>((IOrderable)t).theZOrder);
    
    0 讨论(0)
提交回复
热议问题