[WPF][Silverlight] 讓ListBox中的項目寬度自動延展以佔滿空間的技巧

  • 15199
  • 0
  • RIA
  • 2013-07-14

如果在專案中必需使用ListBox做為物件呈現的容器時,若使用預設的Template,當在執行期改變ListBox寬度的時候,可能會發現,裡面的項目大小並不會跟著ListBox縮放;就算把裡面的項目水平對齊方式改為Stretch,它還是會依然故我,不管ListBox寬度的變化。

 

如果在專案中必需使用ListBox做為物件呈現的容器時,若使用預設的Template,當在執行期改變ListBox寬度的時候,可能會發現,裡面的項目大小並不會跟著ListBox縮放;就算把裡面的項目水平對齊方式改為Stretch,它還是會依然故我,不管ListBox寬度的變化。

但是如果直接把ListBox中的項目寬度直接寫死的話,又很容易影響整體的美感,之前在網路上有找到利用TemplateBinding來讓ListBoxItem的寬度和ViewPort的寬度做繫結的辦法,但是那個方法會使得ListBox的水平ScrollBar一直出現在畫面上,若ListBox調整大小,整個佈局也會跟著「走精」。

不過,其實只要針對ListBox的ItemContainerStyle下手,強制讓ListBoxItem的HorizontalContentAlignment屬性設為Stretch就行啦!!

讓我們來看看下面的範例:

(*若無法正常瀏覽本WPF版範例,煩請參考[Windows7]使用IE9、FireFox與Chrome瀏覽WPF Browser Application(.XBAP)的方式一文調整瀏覽器設定)

*若將滑鼠移到以左右兩個ListBox中的項目上,或是利用兩個ListBox中間的GridSplitter改變ListBox的大小,就可以看出明顯的差異。

 

上面的範例中,左右兩個ListBox裡面的項目都被包在一個Grid中,但是左邊ListBox裡的Grid寬度是固定的,所以不管ListBox的寬度改為多少,裡面的Buy按鈕都還是保持在同一個地方,而右邊的ListBox裡的Grid,則會隨著ListBox自動調整寬度,所以Buy按鈕始終會貼齊ListBox的右側。

要做到像右邊的ListBox的效果,只需要在Resorce中加入以下的XAML:

加入這個Style:
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>

並且將ListBox的ItemContainerStyle設為{StaticResource ListBoxItemStyle}就行啦~~

 

來看看完整的XAML:

 

Page1.xaml
<Page x:Class="Wpf_StretchListBoxItem.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" Title="Page1"
        d:DesignWidth="800" d:DesignHeight="600" ShowsNavigationUI="False" Width="Auto"
        Height="Auto">
    <Page.Resources>
        <Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
        </Style>

        <DataTemplate x:Key="ItemTemplate">

        </DataTemplate>
    </Page.Resources>
    <Border BorderThickness="2" CornerRadius="10" BorderBrush="#FF323232"
            DataContext="{Binding Source={StaticResource SampleDataSource}}">
        <Grid x:Name="LayoutRoot">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.5*" />
                <ColumnDefinition Width="0.5*" />
            </Grid.ColumnDefinitions>
            <GridSplitter Width="3" Background="#FF49C8FD" />
            <ListBox Margin="10" HorizontalContentAlignment="Stretch"
                    ItemsSource="{Binding Collection}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid Width="Auto" Height="Auto" UseLayoutRounding="True"
                                Background="Transparent" MinWidth="300">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="30" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="70" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="0.3*" />
                                <RowDefinition Height="0.7*" />
                            </Grid.RowDefinitions>
                            <Border HorizontalAlignment="Stretch" Margin="0" Grid.RowSpan="1"
                                    VerticalAlignment="Center" d:LayoutOverrides="Width"
                                    CornerRadius="3" Background="#FF292828">
                                <TextBlock Text="{Binding Id}" Height="15.96" FontWeight="Bold"
                                        TextAlignment="Center" Foreground="White" Margin="5,0" />
                            </Border>
                            <TextBlock Text="{Binding Name}" Grid.RowSpan="1" Grid.Column="1"
                                    HorizontalAlignment="Stretch" VerticalAlignment="Center"
                                    Grid.ColumnSpan="1" d:LayoutOverrides="GridBox"
                                    Margin="10,0,0,0" FontWeight="Bold" FontSize="13.333" />
                            <Image Source="{Binding Picture}" HorizontalAlignment="Left" Height="64"
                                    Width="64" Grid.Row="1" VerticalAlignment="Center"
                                    Grid.Column="1" Margin="0" Grid.ColumnSpan="1" />
                            <TextBlock Text="{Binding Price}" Grid.RowSpan="1" Grid.Row="1"
                                    HorizontalAlignment="Right" VerticalAlignment="Center"
                                    Grid.Column="1" Margin="0" d:LayoutOverrides="Width"
                                    FontWeight="Bold" FontSize="16" Foreground="Red" />
                            <Button x:Name="button" Content="Buy" Grid.Column="2"
                                    Margin="8,7.96,8,19.96" Grid.RowSpan="1" Width="50" Height="50"
                                    HorizontalAlignment="Center" VerticalAlignment="Center"
                                    Grid.Row="1" Visibility="Hidden" />
                        </Grid>
                        <DataTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Visibility" TargetName="button" Value="Visible" />
                            </Trigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <ListBox Grid.Column="1" Margin="10" HorizontalContentAlignment="Stretch"
                    ItemsSource="{Binding Collection}"
                    ItemContainerStyle="{StaticResource ListBoxItemStyle}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid UseLayoutRounding="True" Background="Transparent" Height="Auto"
                                Width="Auto" MinWidth="300">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="30" />
                                <ColumnDefinition Width="0.903*" />
                                <ColumnDefinition Width="70" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="0.3*" />
                                <RowDefinition Height="0.7*" />
                            </Grid.RowDefinitions>
                            <Border HorizontalAlignment="Stretch" Margin="0" Grid.RowSpan="1"
                                    VerticalAlignment="Center" d:LayoutOverrides="Width"
                                    CornerRadius="3" Background="#FF292828">
                                <TextBlock Text="{Binding Id}" Height="15.96" FontWeight="Bold"
                                        TextAlignment="Center" Foreground="White" Margin="5,0" />
                            </Border>
                            <TextBlock Text="{Binding Name}" Grid.RowSpan="1" Grid.Column="1"
                                    HorizontalAlignment="Stretch" VerticalAlignment="Center"
                                    Grid.ColumnSpan="1" d:LayoutOverrides="GridBox"
                                    Margin="10,0,0,0" FontWeight="Bold" FontSize="13.333"
                                    Foreground="White" />
                            <Image Source="{Binding Picture}" HorizontalAlignment="Left" Height="64"
                                    Width="64" Grid.Row="1" VerticalAlignment="Center"
                                    Grid.Column="1" Margin="0" Grid.ColumnSpan="1" />
                            <TextBlock Text="{Binding Price}" Grid.RowSpan="1" Grid.Row="1"
                                    HorizontalAlignment="Right" VerticalAlignment="Center"
                                    Grid.Column="1" Margin="0" d:LayoutOverrides="Width"
                                    FontWeight="Bold" FontSize="16" Foreground="Red" />
                            <Button x:Name="button" Content="Buy" Grid.Column="2"
                                    Margin="8,7.96,8,19.96" Grid.RowSpan="1" Width="50" Height="50"
                                    HorizontalAlignment="Center" VerticalAlignment="Center"
                                    Grid.Row="1" Visibility="Hidden" />
                        </Grid>
                        <DataTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Visibility" TargetName="button" Value="Visible" />
                            </Trigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

        </Grid>
    </Border>
</Page>

 

就這麼簡單!!

最後一樣附上專案原始碼,請自行服用: