WPF 中的置于前台

发布于 2024-11-02 02:08:35 字数 361 浏览 1 评论 0原文

我需要在 WPF 中将自定义控件置于前面。

伪代码

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

我知道,我知道有一个ZIndex,但仍然不明白如何将简单的WinForm BringToFront 替换为Parent.SetZIndex(this, ?MaxZIndex(parent)? + 1)

也许在像 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?!..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

谈下烟灰 2024-11-09 02:08:35

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

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);
    }
  }
东走西顾 2024-11-09 02:08:35

实际上,您所希望的最好的结果就是使元素相对于同一父面板中的任何同级元素(例如 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 的更改没有立即反映在 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 时, 这个问题是相关的。大多数其他控件都有一个子控件,但您仍然需要将它们向前移动以使其中任何一个子控件成为最顶层。

最后,装饰器是将事物置于一切之上的好方法,但它们不是主视觉树的一部分。所以我不确定这是否适用于你的情况。

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.

挽容 2024-11-09 02:08:35

我尝试了 canvas.zindex 但它不起作用,但对我来说的解决方案是在 Popup 控件中使用 Border:

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

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>
近箐 2024-11-09 02:08:35

我找到了更好的解决方案。明白了:

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,则该方法有效。

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.

薄暮涼年 2024-11-09 02:08:35

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

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

第一行将其带到前面,第二行阻止它永久位于前面。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文