# ViewBox 只有寬度伸縮(viewbox stretch horizontally only) 如果希望視窗內容會依照視窗大小縮放,通常會採用ViewBox,但如果今天只有水平要伸縮,垂直要出現ScrollBar呢? 首先,要先知道一個寫WPF時,微軟沒有明講的事情(至少我以前不知道),就是元件在沒有手動設定高度的時候,預設都是無限(double.PositiveInfinity),但螢幕不是無限大的阿,設為無限又是怎麼變成我們看到的高度呢? 因為元件的高度雖然是無限,但實際上在繪製之前,就會呼叫一個叫做MeasureOverride的函數,他會計算元件真正的高度,最後才被繪製出來,有時候看到有人在自訂元件的時候,也會透過複寫(override)這個函數,達到調整元件高度的目的。 然後還要說到ScrollViewer,這個元件跟其他元件一樣,預設高度也是無限(這邊指的是元件本身),他計算高度的時候會從他的外層去抓(在以下範例中就是Grid),但可以看到Row1的高度是Auto,Auto其實就是無限,但是Grid的Auto不太一樣的是,他會用內容的高度計算高度,於是呼,最終會往回找到ViewBox裡面內容的高度,所以Grid、Row1、ScrollViewer會變得跟Button延伸後一樣高,ScrollViewer都長高了,ScrollBar當然也就不會出現了。 整理步驟為: 1. ViewBox問ScrollViewer高度 2. ScrollViewer問Grid高度 3. Grid問其內容ViewBox高度 4. ViewBox把Button伸縮後,跟Grid說高度 5. 所以ScrollViewer變得跟內容一樣高,所以ScrollBar不會顯示,就算設為顯示也無作用 錯誤示範: ```wpf <Window Width="1920" Height="1080" ... > <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBlock Text="Head, and not stretch"/> <ScrollViewer Grid.Row="1"> <ViewBox> <Button Context="Button" Margin="10" Padding="10" Width="100" Height="300"/> </ViewBox> </ScrollViewer> </Grid> </Windows> ``` **根本就是在鬼打牆,真虧WPF還有辦法算出高度** 所以知道要怎麼解決的嗎? 問題就在於Grid的RowDefinition高度被設為Auto,所以才會讓他去問內容物的高度,如果是"\*",高度就會是整個Grid所剩餘空間,跟內容的高度就無關了,所以要改成這樣。 正確作法: ```wpf <Window Width="1920" Height="1080" ... > <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Text="Head, and not stretch"/> <ScrollViewer Grid.Row="1"> <ViewBox> <Button Context="Button" Margin="10" Padding="10" Width="100" Height="300"/> </ViewBox> </ScrollViewer> </Grid> </Windows> ``` **下課!** ###### tags: `C#` `WPF` `Page` `MVVM`