You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

344 lines
21 KiB

<reactive:ReactiveUserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:AuroraDesk.Presentation.ViewModels.Pages"
xmlns:reactive="using:ReactiveUI.Avalonia"
xmlns:heroicons="clr-namespace:HeroIconsAvalonia.Controls;assembly=HeroIconsAvalonia"
xmlns:converters="using:AuroraDesk.Presentation.Converters"
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800"
x:Class="AuroraDesk.Presentation.Views.Pages.ImageGalleryPageView"
x:DataType="vm:ImageGalleryPageViewModel">
<reactive:ReactiveUserControl.Resources>
<converters:FilePathToImageSourceConverter x:Key="FilePathToImageSourceConverter"/>
<converters:IsGreaterThanZeroConverter x:Key="IsGreaterThanZeroConverter"/>
<converters:InvertedBoolConverter x:Key="InvertedBoolConverter"/>
<converters:IsZeroConverter x:Key="IsZeroConverter"/>
</reactive:ReactiveUserControl.Resources>
<Design.DataContext>
<vm:ImageGalleryPageViewModel />
</Design.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 顶部工具栏(用户交互层:按照 images.md) -->
<Border Grid.Row="0"
Background="{StaticResource BackgroundLight}"
BorderBrush="{StaticResource BorderLight}"
BorderThickness="0,0,0,1"
Padding="20,15">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- 标题和状态信息 -->
<StackPanel Grid.Column="0">
<TextBlock Text="图片浏览"
FontSize="24"
FontWeight="Bold"
Foreground="{StaticResource TextPrimary}"/>
<TextBlock Text="{Binding StatusMessage}"
FontSize="14"
Foreground="{StaticResource SecondaryGrayDark}"
Margin="0,5,0,0"/>
<StackPanel Orientation="Horizontal" Margin="0,8,0,0" Spacing="15">
<TextBlock Text="{Binding SelectedDirectory}"
FontSize="12"
Foreground="{StaticResource TextSecondary}"
TextTrimming="CharacterEllipsis"
MaxWidth="600"/>
<TextBlock Text="{Binding TotalImageCount, StringFormat='共 {0} 张图片'}"
FontSize="12"
Foreground="{StaticResource TextSecondary}"
IsVisible="{Binding TotalImageCount, Converter={StaticResource IsGreaterThanZeroConverter}}"/>
</StackPanel>
</StackPanel>
<!-- 操作按钮(Win11风格) -->
<Button Grid.Column="1"
Content="选择目录"
Command="{Binding SelectDirectoryCommand}"
HorizontalAlignment="Right"
Padding="20,10"
Margin="0,0,0,0">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{StaticResource PrimaryBlue}"
BorderBrush="{StaticResource PrimaryBlue}"
BorderThickness="1"
CornerRadius="6"
Padding="{TemplateBinding Padding}">
<ContentPresenter Content="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Border>
<!-- 主要内容区域(渲染层:按照 images.md) -->
<Grid Grid.Row="1">
<!-- 加载指示器(Win11风格加载动画) -->
<Border Background="{StaticResource BackgroundLight}"
IsVisible="{Binding IsLoading}"
ZIndex="100">
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="20">
<TextBlock Text="正在加载图片..."
FontSize="16"
Foreground="{StaticResource TextPrimary}"
HorizontalAlignment="Center"/>
</StackPanel>
</Border>
<!-- 图片网格列表(虚拟化显示:按照 images.md) -->
<!-- UI布局:采用WrapPanel作为ListBox的容器,每项为固定大小卡片 -->
<!-- 虚拟化机制:启用VirtualizingPanel.IsVirtualizing="True" -->
<Grid IsVisible="{Binding IsLoading, Converter={StaticResource InvertedBoolConverter}}">
<!-- 使用 ScrollViewer + ItemsControl 替代 ListBox,更好地控制滚动条 -->
<ScrollViewer x:Name="MainScrollViewer"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Background="Transparent">
<ItemsControl x:Name="ImageItemsControl"
ItemsSource="{Binding Images}"
Background="Transparent">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- 使用WrapPanel实现网格布局(每行约6个项目) -->
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Background="Transparent"
BorderThickness="0"
Padding="0"
Command="{Binding $parent[UserControl].DataContext.SelectImageCommand}"
CommandParameter="{Binding}">
<Border Background="{StaticResource BackgroundWhite}"
BorderBrush="{StaticResource BorderLight}"
BorderThickness="2"
CornerRadius="8"
Padding="8"
Width="200"
Height="260">
<Border.Effect>
<DropShadowEffect Color="{StaticResource ShadowBlack}"
Opacity="0.15"
BlurRadius="8"
OffsetX="0"
OffsetY="2"/>
</Border.Effect>
<Border.Styles>
<Style Selector="Border">
<Setter Property="Background" Value="{StaticResource BackgroundWhite}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderLight}"/>
</Style>
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="{StaticResource BackgroundLightHover}"/>
<Setter Property="BorderBrush" Value="{StaticResource PrimaryBlue}"/>
<Setter Property="BorderThickness" Value="2"/>
</Style>
</Border.Styles>
<StackPanel Spacing="8">
<!-- 图片预览(缩略图异步加载) -->
<Border Background="{StaticResource BackgroundDark}"
BorderBrush="{StaticResource BorderMedium}"
BorderThickness="1"
CornerRadius="4"
Width="184"
Height="184"
HorizontalAlignment="Center">
<Grid>
<Image Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center"
MaxWidth="184"
MaxHeight="184">
<Image.Source>
<Binding Path="ThumbnailSource"/>
</Image.Source>
</Image>
<!-- 加载状态指示 -->
<TextBlock Text="加载中..."
FontSize="12"
Foreground="{StaticResource TextSecondary}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsVisible="{Binding IsLoadingThumbnail}"/>
</Grid>
</Border>
<!-- 文件信息 -->
<StackPanel Spacing="4">
<TextBlock Text="{Binding FileName}"
FontSize="12"
FontWeight="SemiBold"
Foreground="{StaticResource TextPrimary}"
TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
MaxHeight="36"/>
<TextBlock Text="{Binding FormattedFileSize}"
FontSize="11"
Foreground="{StaticResource TextSecondary}"/>
<TextBlock Text="{Binding LastModified, StringFormat='{}{0:yyyy-MM-dd HH:mm}'}"
FontSize="10"
Foreground="{StaticResource SecondaryGrayDark}"/>
</StackPanel>
</StackPanel>
</Border>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- 保留 ListBox 作为备用(如果需要选择功能) -->
<ListBox x:Name="ImageListBox"
ItemsSource="{Binding Images}"
Background="Transparent"
SelectionMode="Single"
SelectedItem="{Binding SelectedImage}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
IsVisible="False">
<!-- 隐藏 ListBox,使用上面的 ScrollViewer + ItemsControl -->
<!-- 关键修复:禁用虚拟化,让滚动条能正确显示总高度 -->
<!-- 使用自定义虚拟化逻辑(通过ViewModel的窗口更新) -->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<!-- 使用WrapPanel实现网格布局(每行约6个项目) -->
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate>
<Button Background="Transparent"
BorderThickness="0"
Padding="0"
Command="{Binding $parent[UserControl].DataContext.SelectImageCommand}"
CommandParameter="{Binding}">
<Border Background="{StaticResource BackgroundWhite}"
BorderBrush="{StaticResource BorderLight}"
BorderThickness="2"
CornerRadius="8"
Padding="8"
Width="200"
Height="260">
<Border.Effect>
<DropShadowEffect Color="{StaticResource ShadowBlack}"
Opacity="0.15"
BlurRadius="8"
OffsetX="0"
OffsetY="2"/>
</Border.Effect>
<Border.Styles>
<Style Selector="Border">
<Setter Property="Background" Value="{StaticResource BackgroundWhite}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderLight}"/>
</Style>
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="{StaticResource BackgroundLightHover}"/>
<Setter Property="BorderBrush" Value="{StaticResource PrimaryBlue}"/>
<Setter Property="BorderThickness" Value="2"/>
</Style>
</Border.Styles>
<StackPanel Spacing="8">
<!-- 图片预览(缩略图异步加载) -->
<!-- 按照 images.md:懒加载动画,未加载项显示占位符 -->
<Border Background="{StaticResource BackgroundDark}"
BorderBrush="{StaticResource BorderMedium}"
BorderThickness="1"
CornerRadius="4"
Width="184"
Height="184"
HorizontalAlignment="Center">
<Grid>
<Image Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center"
MaxWidth="184"
MaxHeight="184">
<Image.Source>
<Binding Path="ThumbnailSource"/>
</Image.Source>
</Image>
<!-- 加载状态指示(懒加载动画) -->
<TextBlock Text="加载中..."
FontSize="12"
Foreground="{StaticResource TextSecondary}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsVisible="{Binding IsLoadingThumbnail}"/>
</Grid>
</Border>
<!-- 文件信息 -->
<StackPanel Spacing="4">
<TextBlock Text="{Binding FileName}"
FontSize="12"
FontWeight="SemiBold"
Foreground="{StaticResource TextPrimary}"
TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
MaxHeight="36"/>
<TextBlock Text="{Binding FormattedFileSize}"
FontSize="11"
Foreground="{StaticResource TextSecondary}"/>
<TextBlock Text="{Binding LastModified, StringFormat='{}{0:yyyy-MM-dd HH:mm}'}"
FontSize="10"
Foreground="{StaticResource SecondaryGrayDark}"/>
</StackPanel>
</StackPanel>
</Border>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<!-- 空状态提示 -->
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="15"
IsVisible="{Binding TotalImageCount, Converter={StaticResource IsZeroConverter}}">
<heroicons:HeroIcon Type="Photo"
Width="64"
Height="64"
Foreground="{StaticResource SecondaryGrayDark}"
HorizontalAlignment="Center"/>
<TextBlock Text="请选择一个包含图片的目录"
FontSize="16"
Foreground="{StaticResource TextSecondary}"
HorizontalAlignment="Center"/>
<Button Content="选择目录"
Command="{Binding SelectDirectoryCommand}"
HorizontalAlignment="Center"
Padding="20,10"/>
</StackPanel>
</Grid>
</Grid>
</reactive:ReactiveUserControl>