天天看點

WPF異步載入圖檔,附帶載入中動畫 WPF異步載入圖檔,附帶載入中動畫

WPF異步載入圖檔,附帶載入中動畫 WPF異步載入圖檔,附帶載入中動畫

經過兩天的研究,我翻看了愛桌面HD For Windows的源代碼(你懂得)。終于完成了這個功能。實作的效果如右圖所示:

顯示圖檔清單的,肯定是一個ListBox。通過自定義ListBox的ItemsPanel和ItemTemplate,可以實作ListBox的子項橫排,以及設定子項為圖檔。

在做WPF項目時,我們通常是通過綁定為控件的屬性指派,是以我們要先構造一個資料源并且做一個ViewModel。

資料源,就設定為一個簡單的文本檔案(list.txt)。每行,一個圖檔位址。

示例代碼如下:

下面是ViewModel的代碼(MainViewModel.cs):

在圖上,大家可以看到,有一個載入中的效果,我們的下一個任務,就是把這個效果給做出來。(這個,我照搬的。。)

原圖檔如下:

WPF異步載入圖檔,附帶載入中動畫 WPF異步載入圖檔,附帶載入中動畫

WPF原生并不支援GIF格式的圖檔,并且GIF格式的圖檔色彩也很有限,是以這個載入中效果是PNG圖檔加旋轉動畫完成的。首先,我們要添加一個使用者控件。這個使用者控件中隻有一個Image子控件。在XAML檔案中,将Image控件的URI設定為此圖檔,并且在Image的圖檔載入完成後,開始動畫。XAML(WaitingProgress.xaml)代碼如下:

對應的CS代碼(WaitingProgress.xaml.cs)如下:

接着,咱們就該分析如何獲得圖檔了。因為圖檔可能存在本地磁盤上,也可能存在網絡上,是以需要根據不同的存儲位置,使用不同的方法擷取圖檔(PS:如果使用BitmapImage作為圖像源,并且通過URI加載圖像,那麼,在異步設定Image的Source為此圖像時,會發生對象不屬于此線程的錯誤{大概就是這個錯誤。}。這個錯誤是BitmapImage報錯的,并不是Image控件報錯的。具體原因,不太了解。)

在效果圖中,我們可以看到,這些圖檔不是一下子全部顯示出來的,而是一張接着一張顯示出來的。這裡,就要用到一個泛型先入先出集合Queue<T>。在為清單綁定源時,将資料加載到Queue集合中。然後,建立一個背景線程,由這個背景線程不斷的從集合中取出資料,并且轉化為BitmapImage。并且,在轉換完成後會通知Image控件,圖檔我給你下載下傳完成了,你自己看着辦吧。當所有圖檔都下載下傳完成後,這個背景程序也不會停止,而是處于等待狀态,隻要有新的綁定進來,那麼線程就立刻激活,繼續幹自己該幹的事情。這裡我們又要用到一個類型:AutoResetEvent。原理,就是這麼一個原理,且看代碼(ImageQueue.cs)如下:

代碼中,我們定義了一個委托和一個事件。通知Image控件的重任,就交給這兩元大将了。

接着,我們就來做圖檔顯示清單(ListBox)的效果。我們知道,在Grid控件中,如果一個子控件不設定任何位置或者大小屬性的話,這個子控件是會填滿這個Grid的。是以我們要自定義ListBox的ItemTemplate。讓其包含一個Grid控件。這個Grid控件有兩個子控件,一個是剛才做的進度條控件,無定位、大小屬性。另一是Image控件,這個控件設定大小屬性。

首先,我們先讓進度條控件顯示出來,接着,為ListBox綁定資料源,同時,把要下載下傳的資料壓入下載下傳隊列,并且注冊下載下傳完成的事件,在事件執行時,将進度條隐藏掉,為Image控件設定Source屬性為取到的值并且添加一個漸變動畫。

要實作上述功能,我們就需要添加一個依賴屬性。

至此,這個Demo就算是做完了。我接觸WPF的時間雖然不短,但是真正用的卻是不多。這篇文章中用的很多東西,都是在做這個Demo的時候學的,歡迎大家與我交流。

繼續閱讀