2008-10-08 39 views
12

在推出照片查看器應用程序時遇到問題。 我使用ListBox來顯示包含在ObservableCollection中的圖像。 我將ListBox的ItemsSource綁定到ObservableCollection。在具有超過1000個圖像項目的WPF列表框中,縮放圖像變得很慢

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

我也綁定Image'height與滑塊列表框(滑塊的價值還結合zoombarmanager.ZoomBarWidth.Width)。 但是我發現如果集合變大,比如:包含超過1000個圖像,如果我使用滑塊來改變圖像的大小,它會變得有點慢。 我的問題是。 1.爲什麼它變慢?成爲它試圖放大每個圖像,或者它只是因爲通知(「寬度」)被調用超過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~~> 

但如果我使用上面的風格,我必須使用的ScrollViewer外列表框,否則我不知道如何獲得平滑滾動scrollerbar和wrappanel似乎有沒有默認的滾動條。任何人幫助?據說scrollviewer的listbox性能很差。

+0

綁定每個圖像的高度/寬度是效率極其低下,只使用一個LayoutTransform在ItemsPanel(加答案,這個效果) 。 – user7116 2008-10-08 14:00:31

回答

6

問題是您的新佈局面板是WrapPanel,它不支持虛擬化!它可以創建自己的虛擬WrapPanel ...更多here

還可以閱讀更多關於像一些其他事項IScrollInfo here

我也強烈建議您不要創建一個新的控件模板只是更換佈局面板...而是做到以下幾點:

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

這樣做的好處是,你不需要包裝你的列表框在一個ScrollViewer中!

[UPDATE]同時閱讀Josh Smith的文章this!爲了使WrapPanel包...你還記得要禁用水平滾動...

<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" /> 
3
  1. 我對這個組件並不熟悉,但一般情況下,列表框可​​以一次顯示的項目數量會受到限制。

  2. 解決這類問題的方法是保持在控制可以在可接受的性能水平顯示數內的控制加載圖像的數量。兩種技術是分頁或動態加載。

在尋呼,則在一個時間控件添加到圖像的離散的塊之間進行切換,例如,100,與向前和向後的箭頭,類似於導航數據庫記錄。

通過動態加載,您可以在後臺實現分頁,以便當用戶滾動到最後時,應用程序會自動加載下一批圖片,甚至可能會刪除一批舊圖片以保留反應合理。發生這種情況可能會有一些暫停,並且可能需要一些工作來將控件保持在正確的滾動點上,但這可能是一個可接受的折衷。

+0

謝謝我認爲這種方法可行,但也許很多工作都需要完成。 謝謝! – user25749 2008-10-08 09:29:49

0

什麼是您的PhotoListBoxStyle風格是什麼樣子?如果它正在更改ListBox的ItemsPanelTemplate,那麼很可能您的ListBox不使用VirtualizingStackPanel作爲其基礎列表面板。非虛擬化ListBox對於很多項目來說速度要慢很多。

+0

我現在添加它,你有一些想法如何改進它?謝謝! – user25749 2008-10-08 14:31:08

1

嘗試虛擬化與VirtualizingStackPanel.IsVirtualizing =「真」附加屬性您stackpael。這應該會提高性能。

使用與在ScrollViewer中許多項目列表框是WPF中的另一個已知的性能問題。如果可以,請嘗試擺脫scrollviewer。

如果你的ItemTemplate是有點複雜,你應該考慮使用回收VirtualizationMode。這會告訴你的列表框重用現有的對象,而不是一直創建新的對象。問題的

1

部分是,它是裝載在每個完整的圖像。您必須使用IValueConverter通過在BitmapImage上設置DecodePixelWidthDecodePixelHeight屬性來以縮略圖大小打開每個圖像。以下是我在我的項目的一個例子...

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

} 
2

我建議你不要每幅圖像的寬度/高度屬性綁定,而綁定的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> 
+0

謝謝sixlettervariables,我認爲你的話是有道理的!我會嘗試! – user25749 2008-10-08 14:30:00

+0

我發現它仍然很慢。 – user25749 2008-10-09 03:17:07