Wpf 如何约束容器';s高度到特定内容元素的高度?

Wpf 如何约束容器';s高度到特定内容元素的高度?,wpf,layout,size,panel,element,Wpf,Layout,Size,Panel,Element,我正在尝试做一些看起来应该非常简单的事情,但我不知道怎么做。我有一个非常简单的布局,一个文本框旁边有一个图像,类似于WinForms应用程序中用ErrorProvider装饰的方式。问题是,我希望图像不高于它旁边的文本框。如果我这样布置,说: <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.

我正在尝试做一些看起来应该非常简单的事情,但我不知道怎么做。我有一个非常简单的布局,一个文本框旁边有一个图像,类似于WinForms应用程序中用ErrorProvider装饰的方式。问题是,我希望图像不高于它旁边的文本框。如果我这样布置,说:

<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>

如果图像高于文本框,则该行的大小将与图像的高度一致。如果使用DockPanel或StackPanel,也会发生这种情况

简单的解决方案是将
高度
绑定到
文本框
实际高度
。我肯定这是错的。但什么是对的

编辑

下面是一个我认为错误的例子:在这两种布局(都是水平
StackPanel
s)中,
FontSize
是唯一的变量:

您可以看到,第一个
文本框
被限制为图标的高度,因此在文本下有一个不必要的底部填充。第二个旁边的图标与它旁边的
文本框不相称


碰巧,我找到了一种完全不同(而且更好)的方法来解决这个问题——最初我是通过更改
窗口
上的
FontSize
来缩放布局的,但是使用
ScaleTransform
要简单得多,而且似乎工作得很好。但即便如此,我还是觉得很奇怪,这么难做到这一点。

命名您的文本框,参考图片中的文本框,如下所示

<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}"/> 

您需要一种布局算法,该算法使用与特定元素所需高度相等的高度约束来测量其他元素。虽然现有的几个面板实现会根据以前的面板实现使用的大小减少剩余元素的可用空间,但没有一个面板实现会按照您想要的方式设置约束。如果希望在单个布局过程中描述行为,则需要编写自己的布局算法

例如,您可以通过如下方式覆盖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进行第二次度量,而第二次度量将有一个约束。这是额外的工作,如果第一个孩子想要变大,这会导致奇怪的行为


要正确地执行此操作,您需要自己实施整个测量超越方法。我不打算在这里这样做,因为会有很多与问题无关的代码,这取决于您希望布局如何工作。重要的一点是首先测量特定的元素,并在对其他元素调用measure时使用其DesiredSize来确定availableSize

好吧,就像我说的,这是一个幼稚的解决方案,我怀疑这是错误的——不是因为它不起作用,而是因为绑定到ActualHeight和ActualWidth可能会导致非常明显的性能问题。我使用这个想法来保持图像的高度与组合框中的高度文本相同,并取得了很好的成功。