问题描述
|
我需要先介绍WPF中的自定义控件。
伪代码
OnMouseDown()
{
if (this.parent != null)
this.parent.BringToFront(this);
}
我知道,我知道有一个ZIndex,但仍然不知道如何将简单的WinFormBringToFront
替换为parent.SetZIndex(this,?MaxZIndex(parent)? + 1)
?
也许在诸如WPF之类的很酷的东西中有更好的方法呢?
解决方法
这是一个扩展函数,它将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);
}
}
,实际上,您可以期望的最好的办法是使一个元素相对于同一父面板中的所有同级元素(例如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时,这个问题是相关的。大多数其他控件只有一个孩子,但是您仍然需要将它们提高到最高以使其中任何一个孩子居于首位。
最后,装饰者是将事物置于一切之上的好方法,但它们并不是主要视觉树的一部分。因此,我不确定这是否适合您的情况。
,我尝试了canvas.zindex,但没有用,但是对我有用的解决方案是在Popup控件中使用Border:
<Popup IsOpen=\"True/False\">
<Border Background=\"White\">
<DatePicker/>
</Border>
</Popup>
,我找到了更好的解决方案。得到它:
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,则它可以工作。
,我只测试过Window控件,但是...
this.Topmost = true;
this.Topmost = false;
第一行将其移到最前面,第二行使它永远不会在前面。