我正在尝试做一些似乎应该非常简单的事情,但我却看不出如何。我有一个非常简单的布局,一个TextBox旁边有一个图像,类似于在WinForms应用程序中看起来用ErrorProvider装饰的方式。问题是,我希望图像不高于它旁边的TextBox。如果我这样说出来,请说:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Grid.Column="0" MinWidth="100"/>
<Image Grid.Row="0" Grid.Column="1" Source="error.png" />
</Grid>
如果图像高于TextBox,则行的大小将调整为图像的高度。如果我使用DockPanel或StackPanel,也会发生这种情况。
天真的解决方案是将Height
绑定到TextBox
的{{1}}。我确定这是错的。但是什么是对的?
修改
以下是我看错了的一个示例:在这两种布局中(均为水平ActualHeight
s),StackPanel
是唯一的变量:
您可以看到第一个FontSize
被约束到图标的高度,因此在文本下面有一个不必要的底部填充。第二个旁边的图标超出了它旁边的TextBox
。
实际上,我发现了一种完全不同(并且更好)的方法来处理问题 - 最初我通过更改TextBox
上的FontSize
来扩展我的布局,但使用{{ 1}}更简单,似乎完美无缺。但即便如此,我仍然觉得很难做到这一点。
答案 0 :(得分:2)
为TextBox命名,从Image引用TextBox,如下所示。
<TextBox Name="myTextBox"
Grid.Row="0" Grid.Column="0"
MinWidth="100"/>
<Image Grid.Row="0"
Grid.Column="1"
Source="error.png"
Height="{Binding ActualHeight, ElementName=myTextBox}"/>
答案 1 :(得分:1)
您需要一种布局算法,用于测量高度约束等于特定高度所需高度的其他元素。虽然现有的几个Panel实现将根据先前使用的大小减少剩余元素的可用空间,但它们都不会按照您想要的方式设置约束。如果您希望在单个布局中描述的行为通过,则需要编写自己的布局算法。
例如,您可以通过覆盖StackPanel的行为来接近:
public class SizeToFirstChildStackPanel
: StackPanel
{
protected override Size MeasureOverride(Size constraint)
{
if (Children.Count > 0)
{
var firstChild = Children[0];
firstChild.Measure(constraint);
if (Orientation == Orientation.Horizontal)
{
constraint = new Size(
constraint.Width,
Math.Min(firstChild.DesiredSize.Height, constraint.Height));
}
else
{
constraint = new Size(
Math.Min(firstChild.DesiredSize.Width, constraint.Width),
constraint.Height);
}
}
return base.MeasureOverride(constraint);
}
}
这会将StackPanel的所有子项的高度约束到第一个子项的所需高度(如果面板垂直定向,则为宽度)。
它仍然不理想,因为第一个孩子将通过基类MeasureOverride第二次测量,第二个测量将有一个约束。这是额外的工作,如果第一个孩子想要变大,会导致奇怪的行为。
要做得对,您需要自己实现整个MeasureOverride方法。我不会在这里这样做,因为它会有很多与问题无关的代码,而且取决于你希望布局的确切运行方式。重要的是首先测量特定元素,并在其他人调用Measure时使用DesiredSize来确定availableSize。