13

フォトビューアアプリケーションを開発するときに問題が発生しました。ListBoxを使用して、ObservableCollectionに含まれている画像を表示します。ListBoxのItemsSourceをObservableCollectionにバインドします。

  <DataTemplate DataType="{x:Type modeldata:ImageInfo}">
        <Image 
            Margin="6"
            Source="{Binding Thumbnail}"
            Width="{Binding ZoomBarWidth.Width, Source={StaticResource zoombarmanager}}"
            Height="{Binding ZoomBarWidth.Width, Source={StaticResource zoombarmanager}}"/>
  </DataTemplate>

<Grid DataContext="{StaticResource imageinfolder}">
    <ScrollViewer
        VerticalScrollBarVisibility="Auto" 
        HorizontalScrollBarVisibility="Disabled">
        <ListBox Name="PhotosListBox"
            IsSynchronizedWithCurrentItem="True"
            Style="{StaticResource PhotoListBoxStyle}" 
            Margin="5"
            SelectionMode="Extended" 
            ItemsSource="{Binding}" 
           />
    </ScrollViewer>

また、リストボックスの画像の高さをスライダーでバインドします(スライダーの値もzoombarmanager.ZoomBarWidth.Widthにバインドします)。しかし、コレクションが大きくなると、次のようになります。1000を超える画像が含まれている場合、スライダーを使用して画像のサイズを変更すると、少し遅くなります。私の質問はです。1.なぜ遅くなるのですか?すべての画像をズームしようとするか、notify( "Width")が1000回以上呼び出されたからです。2.この種の問題を解決し、より速くする方法はありますか。

PhotoListBoxStyleは次のようなものです。

    <Style~~ TargetType="{x:Type ListBox}" x:Key="PhotoListBoxStyle">
        <Setter Property="Foreground" Value="White" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBox}" >
                    <WrapPanel 
                        Margin="5" 
                        IsItemsHost="True" 
                        Orientation="Horizontal" 
                        VerticalAlignment="Top"                             
                        HorizontalAlignment="Stretch" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style~~>

ただし、上記のスタイルを使用する場合は、ListBoxの外部でScrollViewerを使用する必要があります。そうしないと、スムーズにスクロールするスクローラーバーを取得する方法がわからず、ラップパネルにデフォルトのスクローラーバーがないようです。誰か助けますか?scrollviewerを使用したリストボックスのパフォーマンスが低いと言われています。

4

6 に答える 6

6

問題は、新しいレイアウト パネルが WrapPanel であり、仮想化をサポートしていないことです! 独自の仮想化 WrapPanel を作成することが可能です... 詳しくはこちら

また、IScrollInfo の実装などの他の問題については、こちらを参照してください。

また、レイアウト パネルを置き換えるためだけに新しいコントロール テンプレートを作成しないことを強くお勧めします。代わりに、次のことを行ってください。

<ListBox.ItemsPanel>
   <ItemsPanelTemplate>
      <WrapPanel Orientation="Horizontal"/>
   </ItemsPanelTemplate>
</ListBox.ItemsPanel>

これを行う利点は、リストボックスをスクロールビューアーでラップする必要がないことです!

[更新] Josh Smith によるこの記事もお読みください! WrapPanel をラップするには...水平スクロールを無効にすることも忘れないでください...

<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
于 2008-10-09T06:46:34.337 に答える
3
  1. 私はこのコンポーネントに詳しくありませんが、一般的に、リストボックスが一度に表示できるアイテムの数には制限があります。

  2. この種の問題を解決する方法は、コントロールに読み込まれるイメージの数を、コントロールが許容可能なパフォーマンス レベルで表示できる数の範囲内に保つことです。これを行う 2 つの手法は、ページングまたは動的読み込みです。

ページングでは、データベース レコードをナビゲートするのと同様に、前方矢印と後方矢印を使用して、一度に 100 枚などの画像の個別のブロックを切り替えるコントロールを追加します。

動的読み込みでは、ユーザーが最後までスクロールすると、アプリケーションが自動的に次の画像のバッチを読み込み、場合によっては古い画像のバッチを削除して応答性を適切に保つように、舞台裏でページングを実装します。これが発生すると少し一時停止し、コントロールを適切なスクロール ポイントに維持するために何らかの作業が必要になる場合がありますが、これは許容できるトレードオフです。

于 2008-10-08T08:56:59.647 に答える
2

個々の画像の Width/Height プロパティをバインドするのではなく、 ListBox のItemsPanelにLayoutTransformをバインドすることをお勧めします。何かのようなもの:

<ListBox.ItemsPanel>
   <ItemsPanelTemplate>
      <StackPanel>
        <StackPanel.LayoutTransform>
           <ScaleTransform
               ScaleX="{Binding Path=Value, ElementName=ZoomSlider}"
               ScaleY="{Binding Path=Value, ElementName=ZoomSlider}" />
        </StackPanel.LayoutTransform>
      </StackPanel>
   </ItemsPanelTemplate>
</ListBox.ItemsPanel>
于 2008-10-08T13:56:32.147 に答える
2

問題の一部は、それぞれに完全なイメージをロードしていることです。でまたはプロパティをIValueConverter設定して、各画像をサムネイル サイズで開くには、 を使用する必要があります。これが私のプロジェクトの1つで使用する例です...DecodePixelWidthDecodePixelHeightBitmapImage

class PathToThumbnailConverter : IValueConverter {
    public int DecodeWidth {
        get;
        set;
    }

    public PathToThumbnailConverter() {
        DecodeWidth = 200;
    }

    public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
        var path = value as string;

        if ( !string.IsNullOrEmpty( path ) ) {

            FileInfo info = new FileInfo( path );

            if ( info.Exists && info.Length > 0 ) {
                BitmapImage bi = new BitmapImage();

                bi.BeginInit();
                bi.DecodePixelWidth = DecodeWidth;
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.UriSource = new Uri( info.FullName );
                bi.EndInit();

                return bi;
            }
        }

        return null;
    }

    public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
        throw new NotImplementedException();
    }

}
于 2008-10-08T13:45:06.833 に答える
1

VirtualizingStackPanel.IsVirtualizing="True" 添付プロパティを使用してスタックパエルを仮想化してみてください。これにより、パフォーマンスが向上します。

スクロールビューアーで多くのアイテムを含むリストボックスを使用することは、wpf 内のもう 1 つの既知のパフォーマンスの問題です。可能であれば、スクロールビューアを取り除くようにしてください。

itemtemplates が少し複雑な場合は、Recycling VirtualizationMode の使用を検討する必要があります。これは、リストボックスに既存のオブジェクトを再利用し、常に新しいオブジェクトを作成しないように指示します。

于 2008-10-08T10:10:40.993 に答える
0

PhotoListBoxStyle スタイルはどのように見えますか? ListBox の ItemsPanelTemplate を変更している場合は、ListBox が基になるリスト パネルとして VirtualizingStackPanel を使用していない可能性が高くなります。仮想化されていない ListBox は、多くのアイテムで非常に遅くなります。

于 2008-10-08T10:06:49.317 に答える