|
|
|
|
<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>
|