在WPF中使用BringToFront

时间:2011-04-14 16:55:30

标签: .net wpf wpf-controls

我需要在WPF中引入自定义控件。

伪代码

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

我知道,我知道 ZIndex ,但仍然不明白如何将简单的WinForm BringToFront替换为{{1} }?

也许有更好的方法在像WPF这样的酷事中做到这一点?!..

5 个答案:

答案 0 :(得分:18)

这是一个扩展函数,它将方法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);
    }
  }

答案 1 :(得分:14)

你真正希望的最好的方法是使一个元素相对于同一父面板中的任何兄弟元素(例如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>

在此示例中,蓝色矩形将显示在顶部。在blog post中对此进行了解释。

Panel.ZIndex的更改也没有立即反映在UI中。有一个私有方法允许刷新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时,this question是相关的。大多数其他控件只有一个孩子,但是你仍然需要将它们带到前面才能使它们成为最顶级的孩子。

最后,Adorners是将事物置于一切之上的好方法,但它们不是主视觉树的一部分。所以我不确定这会对你的情况有效。

答案 2 :(得分:0)

我只测试过Window控件,但是...

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

第一行将其移到最前面,第二行使它永远不会在前面。

答案 3 :(得分:-1)

我尝试了canvas.zindex并且它没有用,但是为我做的解决方案是在Popup控件中使用Border:

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

答案 4 :(得分:-1)

我找到了更好的解决方案。得到它:

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,则它可以正常工作。