6

我有一个标准的 WPF 网格,其中 2 列定义为:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" MinWidth="200" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    ...
</Grid>

我想要实现的是第二列根据其内容自动调整大小,第一列获得所有剩余空间。但是我也希望第一列永远不会少于 200 像素。问题是使用这种配置我的自动列将被切断而不是调整大小。

我真正想要的是 WPF 首先为第一列分配 200 个像素,然后占用所有剩余空间并要求第二列的内容调整自身大小,并限制剩余宽度的最大大小。如果内容需要较少的空间,则应将剩余空间分配给第一列(使其大于 200 像素)。

用例:我的第二列是具有固定纵横比的图像,因此对于给定的高度,有一个最佳宽度。我还有第一列,其中包含一些应该始终可见的控件。如果可用空间比需要的多,我想将空间分配给第一列而不是第二列。

有没有办法使用默认的 WPF 控件来实现这一点,或者我需要为此编写自己的 Grid 吗?

4

3 回答 3

2

听起来您想要的基本上是为您的第二列提供两种不同的模式。当整个图像有足够的空间以当前高度显示时,它应该是自动的,否则它应该在第一列取 200 之后只剩下剩余的空间。要进行这种模式切换,您可以使用转换器并绑定列的宽度。

在这里,您有 2 个基本输入:网格可用的总大小和所需的图像宽度。因为你需要它们,所以你需要一个 IMultiValueConverter。这是计算上述开关的基本实现:

public class AutoColumnConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        double imageWidth = values.OfType<double>().FirstOrDefault();
        double gridWidth = values.OfType<double>().ElementAtOrDefault(1);
        int minWidth = System.Convert.ToInt32(parameter);

        double availableSpace = gridWidth - minWidth;
        if (imageWidth > availableSpace)
            return new GridLength(availableSpace, GridUnitType.Pixel);

        return new GridLength(0, GridUnitType.Auto);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

要使用它,您需要将 Grid 包装在可以绑定到的另一个元素中,而不是 Grid 本身,这实际上将位于可用空间附近,并尝试使用两个定义的列进一步扩展。在这里,我使用 Source.Width 来查找图像所需的宽度。如果您更关心纵横比或者也想考虑高度,您可能需要进行调整。

<Border>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" MinWidth="200" />
            <ColumnDefinition>
                <ColumnDefinition.Width>
                    <MultiBinding ConverterParameter="200">
                        <MultiBinding.Converter>
                            <local:AutoColumnConverter/>
                        </MultiBinding.Converter>
                        <Binding ElementName="Img" Path="Source.Width"/>
                        <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Border}}" Path="ActualWidth"/>
                    </MultiBinding>
                </ColumnDefinition.Width>
            </ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Image x:Name="Img" Grid.Column="1" Stretch="Uniform" StretchDirection="DownOnly"
                Source="..."/>
    </Grid>
</Border>
于 2013-01-22T17:34:47.027 回答
2

试试这个设置 MaxWidth

<Grid Height="200"
          Width="600">
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"
                          MaxWidth="200" />
        <ColumnDefinition Width="Auto" />
      </Grid.ColumnDefinitions>
      <Border Background="Blue"
              Grid.Column="0" />
      <Viewbox Grid.Column="1"
               Stretch="Uniform"
               MaxWidth="400">
        <Border Background="Yellow"
                BorderBrush="Red"
                BorderThickness="4"
                Height="200"
                Width="300" />
      </Viewbox>
    </Grid>
于 2018-04-25T12:00:17.270 回答
1

我唯一一次看到第二列被截断是当第二列的宽度 + 200 大于网格的宽度时。我玩过,也许这对你来说是一个解决方案:

<Grid Height="200"
      Width="600">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"
                      MinWidth="200" />
    <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <Border Background="Blue"
          Grid.Column="0" />
  <Viewbox Grid.Column="1"
           Stretch="Uniform"
           MaxWidth="400">
    <Border Background="Yellow"
            BorderBrush="Red"
            BorderThickness="4"
            Height="200"
            Width="300" />
  </Viewbox>
</Grid>

我尝试写作<ColumnDefinition Width="Auto" MaxWidth="400"/>,但 maxwidth 没有效果。

Viewbox 的 MaxWidth 计算为总宽度 - 如果不明显,则保留 200。

于 2013-01-22T16:19:41.490 回答