限制WPF数据网格中“自动”列的最大宽度

时间:2013-01-22 15:31:52

标签: .net wpf xaml layout resize

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

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

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

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

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

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

3 个答案:

答案 0 :(得分:2)

听起来你想要的基本上是你的第二列有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>

答案 1 :(得分:2)

试试这个 设置MaxWidth

SpeechRecognitionEngine sr = new SpeechRecognitionEngine();
 sr.SetInputToDefaultAudioDevice();
 // Create a grammar that recognizes Wake-up word e.g. your app name
 Choices wakeWord = new Choices();
 wakeWord.Add("Cooper");

 GrammarBuilder gb = new GrammarBuilder();
 gb.Append(wakeWord);
 Grammar g = new Grammar(gb);

 sr.LoadGrammarAsync(g);
 sr.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(sr_SpeechRecognized);

答案 2 :(得分:1)

我看到第二列被切断的唯一一次是当第2列+ 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.