2016-04-12 24 views
0

のための間違った画像を表示I持っているので、同様にディレクトリからすべての項目を一覧表示し、リストビュー:リストビューは、各項目

file system

card gallery

しかし、あなたはこの画像で見ることができるように

1つのイメージテキストが完全にスキップされているため、イメージ自体はまだ順番になっています。それは半分程度から始め、リストのさらに下取得

しかし、彼らは完全にこの例のよう混ぜになって起動します。画像をクリックすると、それが正しいのプレビューを示し

Image 3

右側の画像。

image 4

これは、私はすべての画像をロードするために使用しているコードです:私は、BackgroundWorkerのに追加

Dim imgList As New ImageList 
    Dim imgSize As New Size 
    Dim count As Integer = 0 
    Dim imgFilename As String 

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork 
     'Dim imlTemp As New ImageList 
     Dim dirFiles() As String = IO.Directory.GetFiles(My.Settings.GalleryLocation) 

     'Dim item As New ListViewItem 
     For Each dirFile As String In dirFiles 
      imgFileName = IO.Path.GetFileName(dirFile) 
      Dim img As New System.Drawing.Bitmap(dirFile) 
      Dim imgImage As Image = Image.FromFile(dirFile) 
      'Dim imgHeight As Integer 
      'imgHeight = imgImage.Height 
      imgSize.Width = 120 
      imgSize.Height = 174 
      Threading.Thread.Sleep(10) 
      BackgroundWorker1.ReportProgress(100/((dirFiles.Count + 1) - count), img) 
     Next 
    End Sub 

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged 
     ListView1.SmallImageList = imgList 
     ListView1.LargeImageList = imgList 
     imgList.ImageSize = imgSize 
     imgList.ColorDepth = ColorDepth.Depth32Bit 

     ListView1.Items.Add(imgFilename, count) 
     imgList.Images.Add(e.UserState.Clone) 
     count += 1 
     'ListView1.EnsureVisible(ListView1.Items.Count - 1) 
    End Sub 

前にそれはそう、大量の画像のための驚異的な読み込み時間を持っていました私は、非同期作業を可能にするために背景作業者を実装すると思った。しかし、タスクの開始時に何かが完全に間違っていて、リストを何度か途切れてしまうと、画像3に示すように完全にうんざりしてしまいます。

何が起こっているのか、私がしようとしていることに対する解決策?

答えて

1

ReportProgress()は(わかっている限り)ブロックされていないため、UIが更新できるよりも速くファイルが反復される可能性があります。

この同期を維持するには、更新するアイテムをすべて保持し、ReportProgress()メソッドに渡すカスタムクラスを作成する必要があります。例えば

:あなたのコードに今

Public Class GalleryImage 
    Public Property FullPath As String 
    Public Property FileName As String 
    Public Property [Image] As Image 


    Public Sub New(ByVal File As String) 
     Me.Image = Image.FromFile(File) 'Get the image. 
     Me.FullPath = File 'Save the full path of the image. 
     Me.FileName = Path.GetFileName(File) 'Get the file name. 
    End Sub 
End Class 

(拡張子をファイル名をしたいが、ない場合はまた、あなたがPath.GetFileNameWithoutExtension()を使用することができます)


。まずcounter変数は、ListView1.Items.CountまたはimgList.Images.Countのいずれかで置き換えることができるため、実際には必要ありません。

第2に、imgSize変数またはListViewのSmall-/LargeImageListプロパティを常に設定し続けるべきではありません。そうすることは完全に不要で、物事が遅くなる。 ListViewコントロールのために一度だけイメージリストを設定し、imgSize変数のために、あなたは次のように行うことができます。

Dim ReadOnly imgSize As New Size(120, 174) 

を変数ReadOnlyが、それはのように聞こえるん作ります。それを読むことはできますが、それを変更することはできません。あなたは私たちが今、かなり多くのダウンコードを縮小している見たよう

For Each dirFile As String In dirFiles 
    Threading.Thread.Sleep(10) 'You don't need this Sleep if you don't want to. 

    'Report the progress, declare an in-line version of our class and send it with. 
    BackgroundWorker1.ReportProgress(100/((dirFiles.Count + 1) - ListView1.Items.Count), New GalleryImage(dirFile)) 'A new GalleryImage is created. The property setting is handled by the class itself. 
Next 

:我々はBackgroundWorkerののFor Eachループで始めましょうこれらの他のものを修正するために今すぐ

は、今、私たちはReportProgess()イベントを処理しようとしている。

Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged 
    Dim img As GalleryImage = e.UserState 'Retrieve our class, no need to clone it. 

    imgList.Images.Add(img.Image) 'Add the image first (I don't know for sure, but if you add the image after, wouldn't it require to redraw the ListView an extra time?). 
    ListView1.Items.Add(img.FileName, imgList.Images.Count - 1) 'Add the new item with the values from our class. 
End Sub 

そして最後に、初期化とかの初期設定はForm Loadイベントたとえばで行われる必要があります。

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    'In here we do all the standard settings and initializations. 
    ListView1.SmallImageList = imgList 
    ListView1.LargeImageList = imgList 
    imgList.ImageSize = imgSize 
    imgList.ColorDepth = ColorDepth.Depth32Bit 
End Sub 

それによって、私はそれをすべてカバーしていたはずだと思います。

希望すると便利です。

+0

これは魅力的です!この詳細な回答をありがとうと私はいくつかの愚かな間違いをクリアするのを手伝ってくれました... 私は最後の質問が1つあります:私はリストを更新/リロードしたいのですが、私はリストをクリアしてからバックグラウンドワーカー? –

+0

また、好奇心から、私は周りにこれらの2行を入れ替え: 'imgList.Images.Add(img.Image) ListView1.Items.Add(img.FileName、imgList.Images.Count - 1) ' そして、非常に最初と同じエラーを出していたので、これが問題だったのでしょうか? –

+1

@DominikH:はい、 'ListView'と' imgList'をクリアするだけでBGWを再実行できます。 –

関連する問題