WPF中的ListBox預設使用的ItemsPanel是VirtualizingStackPanel,而不是一般的StackPanel,這樣在一般的使用上雖然不會發生什麼問題,但是當它一碰上Expander,問題就大條了。
首先,請先玩玩下面的範例,將所有的Expander展開,再將所有的Expander收合,看看兩邊有什麼不同之處:
(*若無法正常瀏覽本WPF版範例,煩請參考[Windows7]使用IE9、FireFox與Chrome瀏覽WPF Browser Application(.XBAP)的方式一文調整瀏覽器設定)
我們可以很明顯的發現,左邊的容器在Expander收合之後,還是一樣佔了大部份的版面空間,而沒有隨著Expander收合而變小。
這個其實是因為WPF中的ListBox預設使用的ItemsPanel是VirtualizingStackPanel,而不是一般的StackPanel,這樣在一般的使用上雖然不會發生什麼問題,但是當它一碰上Expander,問題就大條了。
解法呢?很簡單,把ListBox的ItemsPanel改為一般的StackPanel就行啦!!
讓我們來看看上面範例的原始碼:
<Page x:Class="Wpf_ExpanderInListBox.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignWidth="600" d:DesignHeight="400"
Title="Page1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Rectangle Stroke="#FF4B4B4B" RadiusX="10" RadiusY="10" StrokeThickness="2" Grid.ColumnSpan="2"/>
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,2">
<TextBlock Text="Actual Height Of The Left ListBox: " FontSize="13.333" />
<TextBlock Text="{Binding ActualHeight, ElementName=listBox}" FontSize="13.333" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,2">
<TextBlock Text="Actual Height Of Expander1: " FontSize="13.333" />
<TextBlock Text="{Binding ActualHeight, ElementName=expander1}" FontSize="13.333" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,2">
<TextBlock Text="Actual Height Of The Black Rectangle: " FontSize="13.333" />
<TextBlock Text="{Binding ActualHeight, ElementName=rect1}" FontSize="13.333" />
</StackPanel>
<ListBox Margin="5" x:Name="listBox">
<Expander Header="Expander1" x:Name="expander1" Height="auto" Width="auto" IsExpanded="True">
<Rectangle x:Name="rect1" Fill="Black" Stroke="Black" Width="280" Height="70"/>
</Expander>
<Expander x:Name="expander2" Header="Expander2">
<Rectangle x:Name="rect2" Fill="Red" Stroke="Black" Width="280" Height="70"/>
</Expander>
<Expander x:Name="expander3" Header="Expander3">
<Rectangle x:Name="rect3" Fill="White" Stroke="Black" Width="280" Height="70"/>
</Expander>
</ListBox>
</StackPanel>
<StackPanel Grid.Column="1">
<StackPanel Orientation="Horizontal" Margin="10,2">
<TextBlock Text="Actual Height Of The Right ListBox: " FontSize="13.333" />
<TextBlock Text="{Binding ActualHeight, ElementName=listBox}" FontSize="13.333" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,2">
<TextBlock Text="Actual Height Of Expander4: " FontSize="13.333" />
<TextBlock Text="{Binding ActualHeight, ElementName=expander1}" FontSize="13.333" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,2">
<TextBlock Text="Actual Height Of The Green Rectangle: " FontSize="13.333" />
<TextBlock Text="{Binding ActualHeight, ElementName=rect1}" FontSize="13.333" />
</StackPanel>
<ListBox Margin="5" x:Name="listBox1">
<!-- 加入下面這段 -->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<!-- 到這邊為止 -->
<Expander Header="Expander4" x:Name="expander4" Height="auto" Width="auto" IsExpanded="True">
<Rectangle x:Name="rect4" Fill="#FF037200" Stroke="Black" Width="280" Height="70"/>
</Expander>
<Expander x:Name="expander5" Header="Expander5">
<Rectangle x:Name="rect5" Fill="#FFD2DE00" Stroke="Black" Width="280" Height="70"/>
</Expander>
<Expander x:Name="expander6" Header="Expander6">
<Rectangle x:Name="rect6" Fill="#FF7E0193" Stroke="Black" Width="280" Height="70"/>
</Expander>
</ListBox>
</StackPanel>
</Grid>
</Page>
就這麼簡單!!
最後一樣附上專案原始檔,請自行服用: