看一下例子:
<Grid VerticalAlignment="Top" Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock"/>
<Button Grid.Column="1">
<Viewbox>
<Path Height="100" Width="100" Fill="Black" Data="M 0,0 H 100 V 100 H 0 Z" />
</Viewbox>
</Button>
</Grid>
这是一个带矢量图形的按钮,我希望它尽可能小(限制来自爆炸的矢量图形)。
以下是它的样子以及我希望它如何:
有几种可能的解决方案如何克服问题,列举一些:
通过将Width
/ Height
绑定到其他元素(这与设计师有问题):
...
<Button Height="{Binding ActualHeight, ElementName=textBlock}" ...>
...
这通常与 ghost 一起使用:其他人使用的特殊隐形元素(与它没有关系)来布局自己。
通过在Canvas
(魔法容器)中托管元素,但Canvas
本身需要布局。
您可以尝试将Button
放入Canvas
。这将导致父Grid
仅取TextBlock
的高度,但是还有另一个问题:如何定位(布局)Canvas
本身,以便其子项布局正确,kek。< / p>
在上面的示例中,我实际上并不希望TextBlock
成为Button
的姐妹,它们可能重叠(您不会想要按钮)要隐藏,如果可用的大小不够,它应该重叠一些不太重要的东西),我只是希望它们有相同的父级(如果它移动 - 孩子会移动)。困惑?看这里:
<Grid>
<TextBlock ... />
<Button HorizontalAlignment="Right" ... />
</Grid>
这种布局有同样的问题,可以类似地解决。
现在尝试从上面的具体例子中抽象出来。
我实际想要的是:了解如何从容器布局中排除元素。就像元素被折叠一样,所以父容器将测量子大小(除了这个元素),布局子元素然后,在布局完成后,元素突然变得可见并受父容器限制,同时可以使用各种对齐。
我要问的是否有意义?也许自定义容器是这样的?或者我是否会错过现有的和明显的东西?
答案 0 :(得分:1)
如果您想将Path
约束所描述几何体的大小,就像在StretchDirection="DownOnly"
上设置Viewbox
一样简单。
如果真正希望它不要求自己的垂直空间,并且其高度由其布局“邻居”(在本例中为TextBlock
)决定,那么你我需要将它包装在自定义布局容器中。但是你不能简单地从布局中排除 - 至少不完全。如果你这样做,元素总是会以零宽度和高度结束。相反,您可以在两次传递中测量,第一次传递请求子高度为零,第二次传递基于第一次传递后给出的排列大小所需的大小。
我认为下面的容器会给你你想要的东西,但会被警告我没有彻底测试过它。使用风险自负。
public class ZeroHeightDecorator : Border
{
private Size _lastSize;
private Size _idealSize;
protected override void OnVisualChildrenChanged(DependencyObject added, DependencyObject removed)
{
base.OnVisualChildrenChanged(added, removed);
_idealSize = new Size();
_lastSize = new Size();
}
protected override Size MeasureOverride(Size constraint)
{
var child = this.Child;
if (child == null)
return new Size();
if (child.IsMeasureValid)
child.Measure(new Size(Math.Max(_lastSize.Width, constraint.Width), _lastSize.Height));
else
child.Measure(new Size(constraint.Width, 0d));
_idealSize = child.DesiredSize;
return new Size(_idealSize.Width, 0d);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
var child = this.Child;
if (child != null)
{
if (arrangeSize != _lastSize)
{
// Our parent will assume our measure is the same if the last
// arrange bounds are still available, so force a reevaluation.
this.InvalidateMeasure();
}
child.Arrange(new Rect(arrangeSize));
}
_lastSize = arrangeSize;
return arrangeSize;
}
}
更灵活的容器允许您指定最小化的维度:Width
,Height
或Neither
或{{1 }}。随意扩展它:)。
行动中的例子:
Both