Подтвердить что ты не робот

Привести элемент вперед (индекс Z) в Silverlight/WPF

Вся документация и примеры, которые я нахожу в Интернете для установки Z-Index для переноса элемента вперед в Silverlight, используют элемент Canvas в качестве контейнера.

Мои элементы - это элементы границы внутри контейнера ItemsControl в DataTemplate. Я использую события MouseEnter и MouseLeave, чтобы вызвать анимацию в ScaleTransform.ScaleX и ScaleTransform.ScaleY, чтобы они росли при зависании. Поскольку они изменяются и занимают то же место, что и другие элементы в контейнере (контейнерах), самые последние добавленные элементы перекрывают старые элементы (в отличие от текущего элемента изменения размера). Есть ли ЧИСТЫЙ способ перенести текущий элемент в код, где я запускаю свою анимацию, чтобы они перекрывали все остальные элементы при их изменении?

4b9b3361

Ответ 1

Мне пришлось иметь дело с этим.

Скажите, что у вас есть ItemControl с ItemTemplate, установленным в экземпляр настраиваемого элемента управления. Внутри этого контроля вы делаете Canvas.SetZIndex(это, 99). Это не сработает, потому что "this" не является непосредственным дочерним элементом ItemsPontel ItemsControl. Элемент ItemsControl создает ContentPresenter для каждого элемента, отбрасывает его в ItemsPanel и отображает ItemTemplate в ContentPresenter.

Итак, если вы хотите изменить ZIndex внутри своего элемента управления, вы должны найти его ContentPresenter и изменить ZIndex на это. Один из способов...

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

Ответ 2

В WPF есть свойство Panel.ZIndex, которое вы можете установить в триггере:

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

В Style для ContentPresenter мы устанавливаем значение Panel.ZIndex равным 99999, когда IsMouseOver равно true. Он должен находиться на ContentPresenter, а не Border, потому что ContentPresenter являются дочерними элементами панели ItemsControl.

К сожалению, я не думаю, что это свойство дошло до Silverlight...

Ответ 3

Для элемента управления, который использует Grid как LayoutRoot, вы можете просто сделать что-то так же просто, как в самом элементе управления:

Canvas.SetZIndex(this, 999);

Ответ 4

Сначала найдите Максимальное ZIndex всех его дочерних элементов, а затем установите новый 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;
}

Затем присвойте

Canvas.SetZIndex(child, MaxZIndex());

Ответ 5

Во-первых, присоединенное свойство Zindex определено в Canvas и, следовательно, недоступно в других производных панели.

Элемент ItemsControl упорядочивает подэлементы в соответствии с порядком списка. Первый элемент в нижней части стека и последний сверху. С учетом этого все, что вам нужно сделать, это убедиться, что выбранный элемент находится в нижней части списка.

Сначала создайте интерфейс для заказа. Вот так:

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

Теперь реализуйте это в классе, который вы показываете.

Если вы хотите перенести элемент на передний план, дайте ему большое количество и дайте всем другим небольшое число.

Al слева - это фактический порядок. Добавьте что-то вроде этого, и вы установите:

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

Ответ 6

Html работает одинаково. Все элементы списка должны быть братьями и сестрами, если вы хотите выложить их слоями.

Я продлил код выше, чтобы он остановился, если он найдет (например) ItemPresenter. Если ContentPresenter не показывает себя здесь и ItemsPresenter, тогда возвращайтесь к исходному коду.

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

Ответ 7

установите zIndex вашего элемента таким образом

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

zIndex++;

Canvas.SetZIndex(element, zIndex);
  • Возможно, вам нужно проверить, равен ли zIndex int.MaxValue, затем reset "ZIndex".
  • но это почти никогда не происходит