WPF實現(xiàn)動態(tài)加載圖片瀏覽器
在做圖片瀏覽器程序時,遇到圖片數(shù)量巨大的情況(如幾百張、上千張),一次性加載所有圖片會導(dǎo)致界面卡頓甚至程序崩潰。
本文介紹一種 WPF + Prism 實現(xiàn)動態(tài)分頁加載圖片的方法,結(jié)合 ScrollViewer 滾動條觸底檢測,實現(xiàn) “邊滾動,邊加載” 的流暢體驗。
1. 界面設(shè)計:4×4 顯示 + 滾動條
我們希望界面每次顯示 4×4,共 16 張圖片,每張圖片帶有邊框。
XAML示例
<ScrollViewer VerticalScrollBarVisibility="Auto" ScrollChanged="ScrollViewer_ScrollChanged">
<ItemsControl ItemsSource="{Binding Images}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1" Margin="5">
<Image Source="{Binding}" Stretch="Uniform"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>ScrollViewer 包裹 ItemsControl,開啟垂直滾動。
使用 UniformGrid 布局,4列均勻分布。
每張圖片用 Border 包一層,美觀且清晰分隔。
2. 后臺邏輯:ViewModel 分頁加載
ViewModel 負責(zé)管理圖片列表和分頁邏輯。
public class ImageBrowserViewModel : BindableBase
{
private const int PageSize = 16;
private readonly List<string> allImagePaths = new();
public ObservableCollection<BitmapImage> Images { get; } = new();
private int currentPage = 0;
public bool IsLoading { get; private set; }
public void LoadAllImagePaths(string folderPath)
{
allImagePaths.Clear();
var extensions = new[] { ".jpg", ".png", ".bmp" };
var files = Directory.GetFiles(folderPath)
.Where(f => extensions.Contains(Path.GetExtension(f).ToLower()))
.ToList();
allImagePaths.AddRange(files);
currentPage = 0;
Images.Clear();
}
public async Task LoadNextPageAsync()
{
if (IsLoading) return;
IsLoading = true;
var nextImages = allImagePaths
.Skip(currentPage * PageSize)
.Take(PageSize)
.ToList();
foreach (var path in nextImages)
{
await Task.Run(() =>
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = new Uri(path);
bitmap.EndInit();
bitmap.Freeze();
App.Current.Dispatcher.Invoke(() => Images.Add(bitmap));
});
}
currentPage++;
IsLoading = false;
}
}
- LoadAllImagePaths:一次性記錄所有圖片路徑,但不立刻加載圖片內(nèi)容。
- LoadNextPageAsync:每次按頁加載圖片,使用 Task.Run + Dispatcher.Invoke,避免界面卡頓。
這段代碼的作用是從 allImagePaths 列表中取出當(dāng)前頁面所需的圖片路徑,并將它們存儲到 nextImages 列表中。以下是逐行解釋:
代碼片段
var nextImages = allImagePaths
.Skip(currentPage * PageSize)
.Take(PageSize)
.ToList();
逐行解釋
1. var nextImages:
聲明一個變量 nextImages,用于存儲當(dāng)前頁面所需的圖片路徑列表。
2. allImagePaths:
這是一個包含所有圖片路徑的列表,類型為 List<string>。
3. .Skip(currentPage * PageSize):
- currentPage 是當(dāng)前頁面的索引,從 0 開始。
- PageSize 是每頁顯示的圖片數(shù)量,這里定義為 16。
- currentPage * PageSize 計算出當(dāng)前頁面之前的所有圖片路徑的數(shù)量。
- .Skip(currentPage * PageSize) 跳過這些路徑,即跳過當(dāng)前頁面之前的所有圖片路徑。
4. .Take(PageSize):
從跳過后的路徑中取出 PageSize 個路徑,即取出當(dāng)前頁面所需的圖片路徑。
5. .ToList():
將取出的路徑轉(zhuǎn)換為一個新的列表,并賦值給 nextImages。
總結(jié)
這段代碼的作用是從 allImagePaths 中取出當(dāng)前頁面所需的圖片路徑,并將它們存儲到 nextImages 列表中。具體來說,它跳過了當(dāng)前頁面之前的所有圖片路徑,然后取出當(dāng)前頁面所需的圖片路徑數(shù)量(PageSize 個),并將這些路徑存儲到 nextImages 列表中。
3. 滾動到底時加載新圖片
在 ScrollViewer 的 ScrollChanged 事件中,檢測是否接近底部,如果是則請求 ViewModel 加載下一頁:
private async void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
if (scrollViewer.VerticalOffset + scrollViewer.ViewportHeight
>= scrollViewer.ExtentHeight - 50) // 接近底部50像素
{
if (DataContext is ImageBrowserViewModel vm && !vm.IsLoading)
{
await vm.LoadNextPageAsync();
}
}
}
ExtentHeight 是總高度,ViewportHeight 是當(dāng)前可視區(qū)域高度,VerticalOffset 是當(dāng)前滾動位置。
當(dāng)滾動接近底部 50px 內(nèi),就觸發(fā)加載。
4. 總結(jié)
通過以上方法,我們實現(xiàn)了:
- 初始只加載少量圖片,快速打開界面。
- 用戶滾動時,按需分頁加載后續(xù)圖片。
- 界面不卡頓,體驗絲滑流暢。
這種設(shè)計特別適合處理大量圖片瀏覽、視頻幀查看、縮略圖管理器等場景。
到此這篇關(guān)于WPF實現(xiàn)動態(tài)加載圖片瀏覽器的文章就介紹到這了,更多相關(guān)WPF圖片瀏覽器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用InstallerProjects打包桌面應(yīng)用程序的完整步驟
這篇文章主要給大家介紹了關(guān)于C#使用InstallerProjects打包桌面應(yīng)用程序的完整步驟,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
C# 構(gòu)造函數(shù)如何調(diào)用虛方法
這篇文章主要介紹了C# 構(gòu)造函數(shù)如何調(diào)用虛方法,文中講解非常詳細,示例代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07
C#中用foreach語句遍歷數(shù)組及將數(shù)組作為參數(shù)的用法
這篇文章主要介紹了C#中用foreach語句遍歷數(shù)組及將數(shù)組作為參數(shù)的用法,C#的數(shù)組可作為實參傳遞給方法形參,需要的朋友可以參考下2016-01-01
C#使用SevenZipSharp實現(xiàn)壓縮文件和目錄
SevenZipSharp壓縮/解壓(.7z?.zip)”是指使用SevenZipSharp庫進行7z和zip格式的文件壓縮與解壓縮操作,SevenZipSharp是C#語言封裝的7-Zip?API,它使得在.NET環(huán)境中調(diào)用7-Zip的功能變得簡單易行,本文給大家介紹了C#使用SevenZipSharp實現(xiàn)壓縮文件和目錄2025-01-01
C#使用oledb讀取excel表格內(nèi)容到datatable的方法
這篇文章主要介紹了C#使用oledb讀取excel表格內(nèi)容到datatable的方法,涉及C#操作oledb及datatable的相關(guān)技巧,需要的朋友可以參考下2015-05-05

