WPF實(shí)現(xiàn)動(dòng)態(tài)加載圖片瀏覽器
在做圖片瀏覽器程序時(shí),遇到圖片數(shù)量巨大的情況(如幾百張、上千張),一次性加載所有圖片會(huì)導(dǎo)致界面卡頓甚至程序崩潰。
本文介紹一種 WPF + Prism 實(shí)現(xiàn)動(dòng)態(tài)分頁加載圖片的方法,結(jié)合 ScrollViewer 滾動(dòng)條觸底檢測(cè),實(shí)現(xiàn) “邊滾動(dòng),邊加載” 的流暢體驗(yàn)。
1. 界面設(shè)計(jì):4×4 顯示 + 滾動(dòng)條
我們希望界面每次顯示 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,開啟垂直滾動(dòng)。
使用 UniformGrid 布局,4列均勻分布。
每張圖片用 Border 包一層,美觀且清晰分隔。
2. 后臺(tái)邏輯:ViewModel 分頁加載
ViewModel 負(fù)責(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)前頁面所需的圖片路徑,并將它們存儲(chǔ)到 nextImages 列表中。以下是逐行解釋:
代碼片段
var nextImages = allImagePaths .Skip(currentPage * PageSize) .Take(PageSize) .ToList();
逐行解釋
1. var nextImages
:
聲明一個(gè)變量 nextImages,用于存儲(chǔ)當(dāng)前頁面所需的圖片路徑列表。
2. allImagePaths
:
這是一個(gè)包含所有圖片路徑的列表,類型為 List<string>。
3. .Skip(currentPage * PageSize)
:
- currentPage 是當(dāng)前頁面的索引,從 0 開始。
- PageSize 是每頁顯示的圖片數(shù)量,這里定義為 16。
- currentPage * PageSize 計(jì)算出當(dāng)前頁面之前的所有圖片路徑的數(shù)量。
- .Skip(currentPage * PageSize) 跳過這些路徑,即跳過當(dāng)前頁面之前的所有圖片路徑。
4. .Take(PageSize)
:
從跳過后的路徑中取出 PageSize 個(gè)路徑,即取出當(dāng)前頁面所需的圖片路徑。
5. .ToList()
:
將取出的路徑轉(zhuǎn)換為一個(gè)新的列表,并賦值給 nextImages。
總結(jié)
這段代碼的作用是從 allImagePaths 中取出當(dāng)前頁面所需的圖片路徑,并將它們存儲(chǔ)到 nextImages 列表中。具體來說,它跳過了當(dāng)前頁面之前的所有圖片路徑,然后取出當(dāng)前頁面所需的圖片路徑數(shù)量(PageSize 個(gè)),并將這些路徑存儲(chǔ)到 nextImages 列表中。
3. 滾動(dòng)到底時(shí)加載新圖片
在 ScrollViewer 的 ScrollChanged 事件中,檢測(cè)是否接近底部,如果是則請(qǐng)求 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)位置。
當(dāng)滾動(dòng)接近底部 50px 內(nèi),就觸發(fā)加載。
4. 總結(jié)
通過以上方法,我們實(shí)現(xiàn)了:
- 初始只加載少量圖片,快速打開界面。
- 用戶滾動(dòng)時(shí),按需分頁加載后續(xù)圖片。
- 界面不卡頓,體驗(yàn)絲滑流暢。
這種設(shè)計(jì)特別適合處理大量圖片瀏覽、視頻幀查看、縮略圖管理器等場(chǎng)景。
到此這篇關(guān)于WPF實(shí)現(xiàn)動(dòng)態(tài)加載圖片瀏覽器的文章就介紹到這了,更多相關(guān)WPF圖片瀏覽器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# WPF上位機(jī)實(shí)現(xiàn)和下位機(jī)TCP通訊的方法
這篇文章主要介紹了C# WPF上位機(jī)實(shí)現(xiàn)和下位機(jī)TCP通訊的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03C#動(dòng)態(tài)創(chuàng)建Access數(shù)據(jù)庫及密碼的方法
同為微軟的產(chǎn)品,本文將討論的是C#如何創(chuàng)建Access數(shù)據(jù)庫,同時(shí)創(chuàng)建數(shù)據(jù)庫密碼與相關(guān)操作,希望對(duì)大家有所幫助。2015-09-09C#實(shí)現(xiàn)HTML轉(zhuǎn)WORD及WORD轉(zhuǎn)PDF的方法
這篇文章主要介紹了C#實(shí)現(xiàn)HTML轉(zhuǎn)WORD及WORD轉(zhuǎn)PDF的方法,涉及C#實(shí)現(xiàn)HTML、WORD及PDF等文件格式轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下2015-09-09C#實(shí)現(xiàn)對(duì)Json字符串處理實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)對(duì)Json字符串處理,通過一個(gè)json實(shí)例分析了C#進(jìn)行JSON操作的方法,需要的朋友可以參考下2014-09-09