6

次のように定義された2つの列を持つ標準のWPFグリッドがあります。

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

私が達成したいのは、2番目の列がその内容に基づいて自動的にサイズ変更され、最初の列が残りのすべてのスペースを取得することです。ただし、最初の列のピクセル数が200ピクセル未満にならないようにする必要もあります。問題は、この構成では、自動列のサイズが変更されるのではなく、切り取られることです。

私が本当に望んでいるのは、WPFが最初に最初の列に200ピクセルを割り当て、次に残りのすべてのスペースを取り、残りの幅の最大サイズ制限でそれ自体のサイズを設定するように2番目の列のコンテンツに要求することです。コンテンツに必要なスペースが少ない場合は、残りのスペースを最初の列に割り当てる必要があります(200ピクセルより大きくします)。

使用例: 2番目の列はアスペクト比が固定された画像であるため、特定の高さに対して最適な幅があります。また、常に表示されるはずのいくつかのコントロールを含む最初の列があります。必要以上に使用可能なスペースがある場合は、2番目の列ではなく最初の列にスペースを割り当てたいと思います。

デフォルトのWPFコントロールでこれを実現する方法はありますか、それとも独自のグリッドを作成する必要がありますか?

4

3 に答える 3

2

基本的に、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();
    }
}

これを使用するには、グリッド自体の代わりにバインドできる別の要素でグリッドをラップする必要があります。これは、基本的にグリッド自体が使用できるスペースの周りにあり、2つの定義された列でさらに拡張しようとします。ここでは、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 に答える
1

列 2 が切り取られているのを見たのは、列 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 です。

于 2013-01-22T16:19:41.490 に答える