2012-04-13 16 views
2

私は、ディスクから400〜600画像(それぞれ200kbのaproxのサイズを持つ)を読み込み(表示する)必要があるWPFコントロールを構築しています。次はコントロールのコードビハインドです。リストボックスへの非同期画像のロード

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

私はバックグラウンドワーカーを使用することはできませんが、ビューにページリストを割り当てようとしましたが失敗します。

イメージを非同期的に(多分UIを更新して)読み込む方法はありませんか、私が試みているバックグラウンドワーカーのこのアプローチは問題ありません。そして、それは大丈夫です場合、どのように私は(完了イベント内)例外を解決することができます:

Must create DependencySource on same Thread as the DependencyObject. 

おかげ

+1

これは例外を修正することがあります。http://stackoverflow.com/questions/4705726/problem-with-binding-property-typeof-bitmapimage –

+0

@SteveWong感謝を。実際にそれはしました。今、このアプローチがこの作業に適しているかどうかを今すぐにしてください。 –

+0

私は自分自身が常にBackgroundWorkerを他の人に使うことを勧めていると感じています。私が見ているものから、あなたは完全にそれを使用しています。 – Rhyous

答えて

1

、あなたのコードを簡素化<>というより一覧<をのObservableCollection使用>とただのItemsSourceプロパティを割り当てるには一度。

スレッドエラーは、ビットマップを作成し、メインUIスレッドではなくバックグラウンドワーカースレッドのリストに追加するためです。これを回避するには、DispatcherHelper(Laurent BugnionのMVVMLight Framwworkから取得)を使用します。

"Winforms way"のやり方ではなく、多くのWPF開発をやっているなら、MVVMをアプリケーション設計メソドロジと見なすことをお勧めします。全く違った考え方です。

... 
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; 
    } 
} 
関連する問題