ListBox Displaying Horizontal Images WPF

2019-04-02 09:54发布

问题:

I'm trying to create a control in wpf/xaml that will display a horizontal list of images. The width of the listbox to be fixed (no scrollbar). When a new item is added the existing items reduce the amount of the image diplayed to accomodate it (the actual image doesn't reduce just the amount of the image shown). The functionality would be similar to adding a new column to a grid with a relative width property ("*") and the column contains an image with a fixed width. Here's my code so far:

<Window.Resources>
    <ItemsPanelTemplate x:Key="ListBox_HorizontalItems">
        <StackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>

    <DataTemplate x:Key="ListBox_DataTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="50" />
            </Grid.ColumnDefinitions>
            <Image Width="150" Source="{Binding ImageSource}" />
        </Grid>
    </DataTemplate>

    <Style x:Key="ListBox_Style_Horizontal" TargetType="ListBox">
        <Setter Property="Width" Value="150" />-->
        <Setter Property="ItemTemplate" Value="{StaticResource ListBox_DataTemplate}" />
        <Setter Property="ItemsPanel" Value="{StaticResource ListBox_HorizontalItems}" />
    </Style>
</Window.Resources>

<Grid>
    <ListBox Name="lbxImages" Style="{StaticResource ListBox_Style_Horizontal}" Width="250"  Height="100" />
</Grid>

Which is very close to what I need! However I can't work out how to reduce the amount of the image shown when a new item is added to the list. Currently a scrollbar appears when a new item is added. Incase I'm not explaining myself very well here are some screenshots showing the functionality I need:

Can anybody show me how to achieve this? Thanks for any help!

回答1:

Use the following UniformGrid as ItemsPanel:

<ItemsPanelTemplate>
    <UniformGrid Columns="{Binding Path=Items.Count,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"/>
</ItemsPanelTemplate>

Disable horizontal scrolling:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">

Modify ItemTemplate:

<DataTemplate>
    <Image Source="{Binding ImageSource}"
           Stretch="None"
           HorizontalAlignment="Center"/>
</DataTemplate>


回答2:

I find that replacing the ItemsPanelTemplate is not enough to get rid of the scroll bar, because that ItemsPanelTemplate is embedded inside a ScrollViewer, somewhere inside the ListBox. You may also need to remove that ScrollViewer.

I replaced the entire ListBox's Template:

<Style  TargetType="ListBox">        
    <Setter Property="Height" Value="Auto"/>
    <Setter Property="Width" Value="Auto"/>        
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Border 
                    BorderBrush="Red" 
                    BorderThickness="1">
                    <UniformGrid  
                        IsItemsHost="True" 
                        Rows="1">                       
                    </UniformGrid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="ListBoxItem">                    
                <Setter Property="Width" Value="Auto"/>
                <Setter Property="VerticalAlignment" Value="Center"/>                    
                <Setter Property="VerticalContentAlignment" Value="Top"/>                    
                <Setter Property="Height" Value="25"/>
                <Setter Property="Padding" Value="5 0 5 0"/>
                <Setter Property="Background" Value="Transparent" />

                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <Border                                   
                                Background="{TemplateBinding Background}"
                                SnapsToDevicePixels="True">
                                 <!-- Presenter for the UniformGrid: -->
                                <ContentPresenter
                                    HorizontalAlignment="Center"
                                    VerticalAlignment="Center"/>
                            </Border>
                            <ControlTemplate.Triggers>
                        <!-- triggers to indicate selection -->

                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

Also, there is no need to find out the number of columns in the UniformGrid. The system just uses the number of ListBoxItems. IsItemsHost="True" does that for you, I think.