9

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5c7f5cdf-4351-4969-990f-29ce9ec84b87/で質問しましたが、奇妙な動作についての適切な説明がまだありません。

次の XAML を実行すると、列が幅 100 に設定されているにもかかわらず、列 0 の TextBlock の幅が 100 より大きいことが示されます。奇妙なのは、ScrollViewer でラップされていることと関係があるのではないかと思いますが、わかりませんどうして。列に MaxWidth を設定すると正常に動作しますが、Width を設定するとうまくいきません。

  1. 列 0 の幅が尊重されないのはなぜですか?
  2. スクロール ビューアーを削除すると、列のサイズ変更の動作が異なるのはなぜですか?

説明に感謝します!これは私にとって本当のパズルです。

<Window x:Class="WpfApplication2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="300">
    <ScrollViewer HorizontalScrollBarVisibility="Auto" >
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="100" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="textBlock" Text="{Binding ElementName=textBlock, Path=ActualWidth}" />
            <TextBlock Text="column 1" Grid.Column="1" />
            <TextBlock Grid.Row="1" Grid.ColumnSpan="3" Text="text here that is wider than the first two columns combined" />
        </Grid>
    </ScrollViewer>
</Window>
4

4 に答える 4

6

これは非常に良い質問であり、私たちの直感の限界をテストします。グリッドのレイアウト ロジックの実装の詳細を明らかにします。

次の理由により、幅 100 は受け入れられません。

  1. 3 番目の列には、グリッドが幅を与える原因となるものは何もありません。
  2. 2 行目の長いテキストは、最初の 2 列に収まりきらない幅です。
  3. Grid の幅が親によって制約または設定されていない場合、そのレイアウト ロジックは明らかに最後の列ではなく最初の列を拡大します。

MaxWidth を最初の列に配置することで、グリッドのレイアウト ロジックを制限することになるため、2 番目の列に移動して引き延ばします。そのシナリオでは、100 よりも広くなることに注意してください。

ただし、グリッドの幅が特定の値に設定されるか、その親によって制約されるとすぐに (たとえば、ウィンドウに ScrollViewer がない場合)、グリッドの幅は特定の値になり、3 番目の列は幅が設定されている場合でも設定された幅を取得します。空の。これで、グリッドの自動サイズ調整コードが無効になり、列を引き伸ばしてそのテキストを押し込もうとしなくなりました。これは、Grid に特定の幅を設定することで確認できますが、これはまだ ScrollViewer 内にあります。

編集:元のスレッドで MSDN サポートの回答を読んだので、それは正しいと思います。つまり、これはおそらくグリッド自体ではなく、添付プロパティの実装の結果です。ただし、原則は同じです。うまくいけば、私の説明がここでの微妙な点を理解するのに十分明確であることを願っています.

于 2011-04-15T17:50:49.443 に答える
3

簡単な回答: 次
の組み合わせが原因です:
1. グリッド (必要に応じて) を任意のサイズにできる ScrollViewer の存在
2. 明示的な幅を持たないグリッド。
3. 幅が指定されていない列 (列 2)。1* に設定され、最終的なサイズはグリッドや他の列のサイズに依存します。
4. colspan が 3 列にまたがる TextBlock。

1. スクロールビューアーを
削除すると、グリッドはウィンドウのクライアント領域 (この例では約 278 になります) までしか拡大できず、長いテキストブロックはこの幅に収まる必要があります。それ以外の場合はトリミングされます。
2. グリッドの明示的な幅を設定します。これにより、テキストブロックが収まるようにトリミングされます。
3. 列 2 の明示的な幅を設定します。これにより、グリッドに固定幅 (100+100+width_of_col2) が提供され、テキストブロックが収まるように再度トリミングされます。
4. colspan を削除します。colspan を含まず、固定幅が定義されている列は、その幅になります。

これは何が起こっているかです:
これは大まかな説明であり、メジャーとアレンジ パスの正確な説明ではありませんが、かなりのアイデアが得られるはずです。

col0 は 100 で開始し、col1 は 100 で、col2 は 0 で開始します。このグリッドのサイズに基づくと、100+100+0=200 になります。Grid がその子 (テキストブロック) の測定を要求すると、最初の 2 つのテキストブロックが列の幅に収まることが確認されます。ただし、3 番目のテキストブロックには 288 が必要です。グリッドには幅が定義されておらず、スクロールビューアー内にあるため、子の 1 つが必要な場合はサイズを大きくできます。グリッドのサイズを 200 から 288 (つまり 88) に増やす必要があります。これは、そのテキストブロックがまたがる各列 (3 つすべて) が 88/3~=29 ピクセルずつ拡大されることを意味します。これにより、col0=100+29=129、col1=100+29=129、col2=0+29 になります。

これを試してください: 四角形
を含めて、col2 に入れ、四角形の幅を 20 に設定 します。col2 は、必要な長方形として 20 に満足しています。このグリッドの幅に基づくと、100+100+20=220 になります。ただし、列にまたがるテキストブロックがあるため、グリッドのサイズを 220 から 288 (つまり 68) に増やす必要があります。これは、そのテキストブロックがまたがる各列 (3 つすべて) が 68/3~=23 ピクセル拡大されることを意味します。これにより、col0=100+23=123、col1=100+23=123、col2=20+23=43 になります。


HTH。

于 2011-04-15T18:23:37.233 に答える
2

Canvasの代わりにScrollViewer:を使用して問題を示す別の例を次に示します。

<Canvas>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" x:Name="textBlock1" Text="{Binding ElementName=textBlock1, Path=ActualWidth}"/>
        <TextBlock Grid.Column="1" x:Name="textBlock2" Text="{Binding ElementName=textBlock2, Path=ActualWidth}"/>
        <TextBlock Grid.Row="1" Grid.ColumnSpan="3" Width="300"/>
    </Grid>
</Canvas>

この例は、無制限のスペースが与えられた場合、最初の2つの列が誤って33%拡張されることを示しています。SP1が.NET4参照ソースを壊したため、現在これをデバッグするための参照ソースが機能していませんが、ソースファイルの行にこれを率直に特定することは役に立たないので、そのルートに進まないでください。

Grid.MaxWidth代わりに、これは間違いなくバグであることに同意します。値を徐々に大きくして、2つの列の幅は、どれだけ大きくしても100のままにすることで、バグであることを証明できます。ただし、Grid.MaxWidth設定せずGridにaの内側に配置するCanvasと、測定中の値はになりdouble.PositiveInfinity、この値は133の列幅を生成します。その結果、正の無限大のサイズ制約の特殊なケースがどのように処理されないかを推測できます。列サイズの計算中に正しく。

幸いなことに、同じ実験で簡単な回避策が提供されます。aや。などの無制限のスペースを許可する別のコントロール内でが使用されるGrid.MaxWidth場合に、非常に大きな値を指定するだけです。私は次のようなものをお勧めします:GridScrollViewerCanvas

<Grid MaxWidth="1000000">

このアプローチは、サイズ制約が正の無限大のプローブ値を持つことを防ぎ、実際には同じ効果を達成することにより、バグを回避します。

でも、これ:

<Grid MaxWidth="{x:Static sys:Double.PositiveInfinity}">

バグを引き起こします。

于 2011-04-27T05:07:42.350 に答える
0

この問題をバグとして報告しました。

https://connect.microsoft.com/VisualStudio/feedback/details/665448/wpf-grids-columns-width-property-not-honored-when-columnspan-row-forces-grid-to-grow

バグであることに同意する場合は、そのリンクで投票してください。

于 2011-04-28T14:03:18.160 に答える