BringToFront в WPF

Мне нужно запустить пользовательский элемент управления в WPF.

псевдокод

OnMouseDown()
{
    if (this.parent != null)
        this.parent.BringToFront(this);
}

Я знаю, что я знаю, что есть ZIndex, но до сих пор не понимаю, как заменить простой WinForm BringToFront на parent.SetZIndex(this, ?MaxZIndex(parent)? + 1)?

Возможно, есть лучший способ сделать это в такой классной вещи, как WPF?!..

Ответы

Ответ 1

Вот функция расширения, которая добавляет метод BringToFront ко всем элементам FrameworkElements, которые содержатся в панели.

  public static class FrameworkElementExt
  {
    public static void BringToFront(this FrameworkElement element)
    {
      if (element == null) return;

      Panel parent = element.Parent as Panel;
      if (parent == null) return;

      var maxZ = parent.Children.OfType<UIElement>()
        .Where(x => x != element)
        .Select(x => Panel.GetZIndex(x))
        .Max();
      Panel.SetZIndex(element, maxZ + 1);
    }
  }

Ответ 2

На самом деле лучшим, на что вы можете надеяться, является создание элемента самого верхнего по отношению к любым элементам-братьями в одной и той же родительской панели (например, StackPanel, Grid, Canvas и т.д.). Z-порядок элементов в панелях контролируется приложением Panel.ZIndex.

Например:

<Grid>
    <Rectangle Fill="Blue" Width="50" Height="50" Panel.ZIndex="1" />
    <Rectangle Fill="Red" Width="50" Height="50" Panel.ZIndex="0" />
</Grid>

В этом примере синий прямоугольник появится сверху. Это объясняется немного больше в этом сообщении .

Также существует проблема с изменениями Panel.ZIndex, которые не сразу отражаются в пользовательском интерфейсе. Существует частный метод, который позволяет обновлять z-index, но поскольку он закрыт, не рекомендуется использовать его. Чтобы обойти это, вам придется удалить и повторно добавить детей.

Однако вы не можете сделать любой данный элемент самым большим. Например:

<Grid>
    <Grid>
        <Rectangle Fill="Blue" Width="50" Height="50" Panel.ZIndex="1" />
        <Rectangle Fill="Red" Width="50" Height="50" Panel.ZIndex="0" />
    </Grid>
    <Grid>
        <Rectangle Fill="Green" Width="50" Height="50" Panel.ZIndex="0" />
        <Rectangle Fill="Yellow" Width="50" Height="50" Panel.ZIndex="0" />
    </Grid>
</Grid>

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

<Grid>
    <Grid Panel.ZIndex="1">
        <Rectangle Fill="Blue" Width="50" Height="50" Panel.ZIndex="1" />
        <Rectangle Fill="Red" Width="50" Height="50" Panel.ZIndex="0" />
    </Grid>
    <Grid Panel.ZIndex="0">
        <Rectangle Fill="Green" Width="50" Height="50" Panel.ZIndex="0" />
        <Rectangle Fill="Yellow" Width="50" Height="50" Panel.ZIndex="0" />
    </Grid>
</Grid>

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

Наконец, Adorners - хороший способ поставить вещи поверх всего, но они не являются частью основного визуального дерева. Поэтому я не уверен, что это сработает в вашем случае.

Ответ 3

Я попробовал canvas.zindex, и это не сработало, но решение, которое для меня использовало, использует Border в элементе управления Popup:

<Popup IsOpen="True/False">
    <Border Background="White">
        <DatePicker/>
    </Border>
</Popup>

Ответ 4

Я нашел лучшее решение. Получите это:

foreach (var item in Grid1.Children)
{
    if ((item as UIElement).Uid == "StackPan1")
    {
        UIElement tmp = item as UIElement;
        Grid1.Children.Remove(item as UIElement);
        Grid1.Children.Add(tmp);
        break;
    }
}

Это просто пример, а не универсальный метод. Но вы можете использовать его в приложениях с динамическим добавлением элементов управления. Этот код просто добавляет элемент, который вы хотите нанести на вершину, и на UIElementCollection. Он работает, если все ваши элементы имеют одинаковый ZIndex.