简体   繁体   English

在WPF中使用BringToFront

[英]BringToFront in WPF

I need to bring to front a custom control in WPF. 我需要在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) ? 我知道,我知道有一个ZIndex ,但仍然不明白如何将简单的WinForm BringToFront替换为parent.SetZIndex(this, ?MaxZIndex(parent)? + 1)

Perhaps there is a better way of doing it in the such a cool thing like WPF?!.. 也许有更好的方法在像WPF这样的酷事中做到这一点?!..

Here is an extension function that adds the method BringToFront functionality to all FrameworkElements that are contained in a Panel. 这是一个扩展函数,它将方法BringToFront功能添加到Panel中包含的所有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);
    }
  }

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). 你真正希望的最好的方法是使一个元素相对于同一父面板中的任何兄弟元素(例如StackPanel,Grid,Canvas等)最顶层。 The z-order of the items in the panels is controlled by the Panel.ZIndex attached property. 面板中项目的z顺序由Panel.ZIndex附加属性控制。

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. Panel.ZIndex的更改也没有立即反映在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. 有一个私有方法允许刷新z-index,但由于它是私有的,因此使用它不是一个好主意。 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. 在处理ItemsControl时, 这个问题是相关的。 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. 最后, Adorners是将事物置于一切之上的好方法,但它们不是主要视觉树的一部分。 So I'm not sure that would work in your case. 所以我不确定这会对你的情况有效。

I've only tested for a Window control but... 我只测试了一个Window控件,但......

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: 我尝试了canvas.zindex并且它没有用,但是为我做的解决方案是在Popup控件中使用Border:

<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. 此代码只是添加了一个元素,您希望将其置于UIElementCollection的顶部。 It works if all of your elements have the same ZIndex. 如果所有元素都具有相同的ZIndex,则它可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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