2012-04-13 24 views
2

因此,我正在構建一個WPF控件,它需要從磁盤加載(並顯示)400到600張圖像(每張大小爲200Kb aprox)。接下來是控件的代碼隱藏。異步圖像加載到列表框中

private List<BitmapImage> pages = new List<BitmapImage>(); 

     private BackgroundWorker worker; 

     public PagesListBox() 
     { 
      InitializeComponent(); 
      worker = new BackgroundWorker(); 
      worker.WorkerSupportsCancellation = false; 
      worker.WorkerReportsProgress = false; 
      worker.DoWork += worker_DoWork; 
      worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
     } 

     void worker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      List<BitmapImage> pagesList = new List<BitmapImage>(); 
      var files = DirectoryServices.GetFiles(Properties.Settings.Default.PagesScanDirectory, new string[] { "*.tiff", "*.jpg", "*.png", "*.bmp" }); 
      foreach (var file in files) 
      { 
       Uri uri = new Uri(file); 
       pagesList.Add(new BitmapImage(uri)); 
      } 
      e.Result = pagesList; 
     } 

     void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      Pages.ItemsSource = (List<BitmapImage>)e.Result; 
     } 

     internal void LoadPages() 
     { 
      worker.RunWorkerAsync(); 
     } 

     internal List<BitmapImage> AttachPages() 
     { 
      List<BitmapImage> attachedPages = new List<BitmapImage>(); 

      foreach (BitmapImage eachItem in Pages.SelectedItems) 
      { 
       attachedPages.Add(eachItem); 
       pages.Remove(eachItem); 
      } 
      Pages.ItemsSource = null; 
      Pages.ItemsSource = pages; 

      return attachedPages; 
     } 

我嘗試將網頁列表分配給視圖(至極,我不能使用後臺工作),但它失敗。

是否有任何其他方式異步加載圖像(可能更新用戶界面)或這種方法的背景工作者我試圖很好。而且,如果它的罰款,我怎麼能解決異常(完成的事件內):

Must create DependencySource on same Thread as the DependencyObject. 

感謝

+1

這可能修復異常:http://stackoverflow.com/questions/4705726/problem-with-binding-property-typeof-bitmapimage – 2012-04-13 01:59:40

+0

@SteveWong感謝。其實它確實。現在,如果這種方法適合這項任務,你現在呢? – 2012-04-13 02:07:22

+0

我發現自己總是向其他人推薦使用BackgroundWorker,並從我看到的內容中完全使用它。 – Rhyous 2012-04-13 04:02:10

回答

1

爲了簡化代碼,使用的ObservableCollection <>而不是列表<>和公正的分配ItemsSource屬性一旦。

線程錯誤是因爲您正在創建位圖並將其添加到後臺工作線程而不是主UI線程的列表中。爲了避免使用DispatcherHelper(取自Laurent Bugnion的MVVMLight Framwwork)。

我建議你考慮MVVM作爲一種應用程序設計方法,如果你要做很多WPF開發,而不是僅僅採用「Winforms方式」,儘管它是一種完全不同的思維方式。

... 
DispatcherHelper.Initialise() 
... 


private ObservableCollection<BitmapImage> _Pages = new ObservableCollection<BitmapImage>(); 

public PagesListBox() 
{ 
    InitializeComponent(); 
    BackgroundWorker worker = new BackgroundWorker(); 
    worker.WorkerSupportsCancellation = false; 
    worker.WorkerReportsProgress = false; 
    worker.DoWork += worker_DoWork; 
    this.ItemSource = _Pages; 
} 

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var files = DirectoryServices.GetFiles(Properties.Settings.Default.PagesScanDirectory, new string[] { "*.tiff", "*.jpg", "*.png", "*.bmp" }); 
    foreach (var file in files) 
    { 
     DispatcherHelper.CheckBeginInvokeOnUI(()=> 
     { 
      Uri uri = new Uri(file); 
      _Pages.Add(new BitmapImage(uri)); 
     }); 
    } 
} 


public static class DispatcherHelper 
{ 
    public static Dispatcher UIDispatcher { get; private set; } 

    public static void CheckBeginInvokeOnUI(Action action) 
    { 
     if (UIDispatcher.CheckAccess()) 
      action(); 
     else 
      UIDispatcher.BeginInvoke(action); 
    } 

    public static void Initialize() 
    { 
     if (UIDispatcher != null) 
      return; 

     UIDispatcher = Dispatcher.CurrentDispatcher; 
    } 
}