3

サムネイル付きのシンプルなファイル ブラウザを作成しています。カスタム DataTemplate で ListBox を使用して、ObservableCollection にオブジェクトを表示しています。

<DataTemplate>
   <StackPanel Margin="5">
      <Image Source="{Binding Path=ThumbnailPath}"/>
      <Label Background="White" Content="{Binding Path=FileName}"/>
   </StackPanel>
</DataTemplate>

(私のカスタム クラス File の) オブジェクトには、ThumbnailPath と FileName の 2 つの文字列プロパティしかありません。ユーザーがフォルダーを選択すると、BackgroundWorker がファイルのリストを取得し、File クラスのインスタンスを作成します。これらのインスタンスは、BW の ReportProgress を使用して (10 のグループで) UI スレッドにディスパッチされます。イベント ハンドラーでは、ListBox にバインドされた ObservableCollection に追加されます。

問題は、コレクションに少なくとも 20 ~ 30 個のファイルを追加する場合です。ListBox が更新される前に、UI がほぼ 3 秒間フリーズします。フォルダーに何百ものファイルが含まれている場合に何が起こるかを尋ねないでください。すべてがバックグラウンドで適切に準備されているため、WPF が空の Image elements の初期化とレンダリングを開始したときに問題が発生すると思います。DataTemplate から Image をコメント アウトすると、コレクションとそのビューを更新するのに一瞬かかります。

これについて何かできることはありますか?バックグラウンドスレッドでViewオブジェクト全体を作成できることはわかっています(新しいStackPanel、子の新しいLabelと新しいImageの追加、値の設定)が、DataBindingとテンプレートの全体的なポイントは、これを行う必要を避けることです...だから応答性を失うことなく、DataTemplate の Image で ListBox を埋めるにはどうすればよいですか?

PS: 実際のサムネイルは FFmpeg によって生成され、ファイルに保存されますが、このプロセスはすべてのアイテム (空白の画像オブジェクト) が表示された後にのみ開始されるため、この質問のコンテキストでは関係ありません。

4

1 に答える 1

0

これを試して:

ThumbnailPath を BitmapImage のタイプに変更します。

プロパティの使用を設定する場合

BitmapImage bi1 = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block
bi1.BeginInit();
bi1.UriSource = new Uri(@"C:\filepath.jpg");
 To save significant application memory, set the DecodePixelWidth or   
// DecodePixelHeight of the BitmapImage value of the image source to the desired  
// height or width of the rendered image. If you don't do this, the application will  
// cache the image as though it were rendered as its normal size rather then just  
// the size that is displayed. 
// Note: In order to preserve aspect ratio, set DecodePixelWidth 
// or DecodePixelHeight but not both.
bi1.DecodePixelWidth = 200;
bi1.EndInit();
bi1.Freeze();

//if you do not Freeze, your app will leak memory.
于 2013-08-12T04:48:54.723 に答える