简体   繁体   中英

BringToFront in WPF

I need to bring to front a custom control in WPF.

pseudoCode

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

I know, I know that there are a ZIndex , but still don't understand how to replace the simple WinForm BringToFront to parent.SetZIndex(this, ?MaxZIndex(parent)? + 1) ?

Perhaps there is a better way of doing it in the such a cool thing like WPF?!..

Here is an extension function that adds the method BringToFront functionality to all FrameworkElements that are contained in a Panel.

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

Really the best that you can hope for is to make an element top-most with respect to any sibling elements in the same parent Panel (such as StackPanel, Grid, Canvas, etc). The z-order of the items in the panels is controlled by the Panel.ZIndex attached property.

For example:

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

In this example, the blue rectangle would appear on top. This is explained a bit more in this blog post .

There is also an issue with changes to the Panel.ZIndex not being immediately reflected in the UI. There is a private method that allows refreshes the z-index, but since it's private it's not a good idea to use it. To work-around it, you'd have to remove and re-add the children.

You cannot however make any given element top-most. For example:

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

In this case, the yellow rectangle will be displayed. Because the second inner grid is shown on top of the first inner grid and all it's content. You'd have to alter it like so to bring the blue rectangle to the top:

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

When dealing with an ItemsControl, this question is relevant. Most other controls have a single child, but you'd still need to bring them forward to make any of it's children top-most.

Finally, Adorners are a good way to put things on top of everything, but they are not part of the main visual tree. So I'm not sure that would work in your case.

I've only tested for a Window control but...

this.Topmost = true;
this.Topmost = false;

The first line brings it to the front, the second line stops it from being permanently on front.

I tried canvas.zindex and it didn't work, but the solution that did for me is using Border in a Popup control:

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

I found better solution. Get it:

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

It is just example, not universal method. But you can use it in apps with dynamic adding of controls. This code just adds an element which you want to put on a top to the and of the UIElementCollection. It works if all of your elements have the same ZIndex.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM