Как сделать WPF ListView горизонтальным с растянутым изображением в соответствии с высотой?

1

Мне нужна галерея, в которой отображаются изображения с метками в горизонтальном ListView.

Каждый элемент списка - это просто изображение с меткой:

<DataTemplate x:Key="ImageItemTemplate">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="4*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Source="{Binding Image}" Stretch="UniformToFill" />
        <Label Grid.Row="1" Content="{Binding Title}" />
    </Grid>
</DataTemplate>

Чтобы сделать ListView горизонтальным, я заменяю ListView.ItemsPanel горизонтальной StackPanel:

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>
</ListView.ItemsPanel>

Теперь у меня есть что-то вроде этого:

Изображение 174551

Но я хочу, чтобы каждое изображение растягивалось, чтобы взять полную высоту ListView (минус достаточная высота для метки), сохраняя соотношение сторон, поэтому я заменяю ListView.ItemContainerStyle:

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Stretch" />
    </Style>
</ListView.ItemContainerStyle>

Но я понятия не имею, почему ширина каждого элемента не растягивается, а вместо этого разрезается:

Изображение 174551

Пожалуйста, помогите, спасибо!

РЕДАКТИРОВАТЬ:

Весь xaml показан следующим образом:

<UserControl x:Class="Test.ImageGalleryControl"
        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">
    <UserControl.Resources>
        <DataTemplate x:Key="ImageItemTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="4*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Image Grid.Row="0" Source="{Binding Image}" Stretch="UniformToFill" />
                <Label Grid.Row="1" Content="{Binding Title}" />
            </Grid>
        </DataTemplate>
    </UserControl.Resources>

    <Grid>
        <ListView x:Name="MyImageList" ItemTemplate="{StaticResource ImageItemTemplate}">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="VerticalContentAlignment" Value="Stretch" />
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
        </ListView>
    </Grid>
</UserControl>
Теги:
wpf
listview

5 ответов

3
Лучший ответ

Попробуй это

путем установки высоты ListView в Itemtemplate (grid).

<ListView  x:Name="MyImageList">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Stretch" />
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid Height="{Binding ElementName=MyImageList,Path=ActualHeight}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="4*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Image Grid.Row="0" Source="Screenshot_3.png" Stretch="UniformToFill" />
                <Label Grid.Row="1" Content="fghfgh" />
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Обновить

установив VerticalScrollBarVisibility = "Скрытый" или отключенный и добавив маржу, вы можете решить эту проблему, но правильное решение ниже

эта вертикальная панель прокрутки происходит из-за поля по умолчанию и заполнения в стиле по умолчанию Listview и ListviewItem. Вы можете добиться желаемого результата, отредактировав стиль listview и listviewItem

рабочий образец (без вертикальной полосы прокрутки)

Ресурс

<Window.Resources>
    <Style TargetType="{x:Type ListView}">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="#FFABADB3"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
        <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListView}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" Height="{TemplateBinding Height}" BorderThickness="0" Background="{TemplateBinding Background}" Padding="0" SnapsToDevicePixels="True">
                        <ScrollViewer Focusable="False" Padding="0" >
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </ScrollViewer>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Background" TargetName="Bd" Value="White"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="#FFD9D9D9"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsGrouping" Value="True"/>
                                <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="False"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="FocusVisualStyle">
            <Setter.Value>
                <Style>
                    <Setter Property="Control.Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"  Background="{TemplateBinding Background}" Margin="0,-1,5,-1" SnapsToDevicePixels="True">
                        <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="#1F26A0DA"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="#A826A0DA"/>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                <Condition Property="IsSelected" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="#3DDADADA"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="#FFDADADA"/>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                <Condition Property="IsSelected" Value="True"/>
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" TargetName="Bd" Value="#3D26A0DA"/>
                            <Setter Property="BorderBrush" TargetName="Bd" Value="#FF26A0DA"/>
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

окно

<ListView  x:Name="MyImageList">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <Grid Height="{Binding ElementName=MyImageList,Path=ActualHeight}">
        <Grid.RowDefinitions>
            <RowDefinition Height="4*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Source="Screenshot_3.png" Stretch="UniformToFill" />
        <Label Grid.Row="1" Content="fghfgh"/>
    </Grid>
    <Grid  Height="{Binding ElementName=MyImageList,Path=ActualHeight}">
        <Grid.RowDefinitions>
            <RowDefinition Height="4*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Source="Screenshot_3.png" Stretch="UniformToFill" />
        <Label Grid.Row="1" Content="fghfgh"/>
    </Grid>
</ListView>
  • 0
    Этот ответ работает хорошо, за исключением того, что присутствует дополнительная вертикальная полоса прокрутки. Я предполагаю, что это потому, что установка Grid.Height в MyImageList.ActualHeight не оставляет вертикальное пространство для горизонтальной полосы прокрутки. Обходной путь состоит в том, чтобы минус некоторый провал от ActualHeight, но тогда мы не можем сказать, насколько это правильно.
  • 0
    @peter, пожалуйста, смотрите обновление
Показать ещё 1 комментарий
0

"простое решение с использованием ItemsControl" by @pushpraj действительно помогло мне после длительного поиска аналогичной функции. Я новичок в WPF, но все еще пытался использовать ListView и Ribbon с шаблонами ItemsControl, но не получил результат, который я хотел. Небольшое изменение в соответствии с моим требованием, я сделал растяжение изображения равномерным, Stretch = "Uniform". Спасибо за блог.

0

простое решение с помощью ItemsControl

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="ImageItemTemplate">
            <Grid Height="{Binding ActualHeight,RelativeSource={RelativeSource FindAncestor,AncestorType=ItemsControl}}"
                  Margin="2,2,2,-25"
                  VerticalAlignment="Top">
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="auto" />
                </Grid.RowDefinitions>
                <Image Grid.Row="0" Source="{Binding Image}" Stretch="UniformToFill" />
                <Label Grid.Row="1" Content="{Binding Title}" />
            </Grid>
        </DataTemplate>
    </Grid.Resources>
    <ScrollViewer HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Hidden">
        <ItemsControl x:Name="MyImageList"
                      ItemTemplate="{StaticResource ImageItemTemplate}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </ScrollViewer>
</Grid>
0
<Image Grid.Row="0" Source="{Binding Image}" Stretch="Fill" />

но он не будет поддерживать пропорции изображения. Используйте Stretch = "Uniform", чтобы сохранить соотношение сторон независимо от размера элемента управления изображением. Вы можете статически указать высоту управления изображением и использовать Stretch = "Uniform" для настройки как формата изображения, так и размера элемента управления изображением.

  • 0
    Но это не ответ на вопрос. Кажется, он хочет создать что-то вроде картинной галереи без ограничений по ширине элементов.
0

Попробуйте изменить свойство растяжения. Хмм, не могу добавить код...

попробуйте установить Stretch = "Uniform" на изображение

<Image Grid.Row="0" Source="{Binding Image}" Stretch="Uniform" />
  • 0
    Я пытался, но теперь это как первая картинка в вопросе.
  • 0
    Пожалуйста, покажите весь ListView XAML, потому что я создал CustomControl (не отредактированный стиль элемента) и все работает нормально
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню