2014-08-27 25 views
5

Tôi đang sử dụng StackPanel để bố cục một số điều khiển theo chiều dọc (ví dụ: Tiêu đề, tiêu đề phụ, hộp danh sách, dấu tách, hộp danh sách, v.v.).Cải thiện hiệu suất cho ListBox lớn trong StackPanel?

StackPanel là con của ScrollViewer để đảm bảo nội dung của nó luôn có thể cuộn được.

Một trong các điều khiển trong StackPanel là một ListBox.

Các mục của nóSource là dữ liệu được liên kết với một bộ sưu tập khổng lồ và một DataTemplate phức tạp được sử dụng để nhận ra từng mục.

Thật không may, tôi nhận được hiệu suất thực sự kém (CPU/bộ nhớ cao) với nó.

tôi đã cố gắng

  • thiết ItemsPanel của ListBox để một VirtualizingStackPanel, và
  • trọng ControlTemplate của nó để chỉ một ItemsPresenter (loại bỏ ScrollViewer của ListBox).

Nhưng không có sự khác biệt về hiệu suất. Tôi đoán StackPanel cung cấp cho trẻ em nội bộ của nó chiều cao vô hạn trong khi đo?

Khi tôi thay thế ScrollViewer và StackPanel bằng các bảng/bố cục khác (ví dụ: Grid, DockPanel) và hiệu suất được cải thiện đáng kể, dẫn tôi tin rằng nút cổ chai cũng như giải pháp đang được ảo hóa.

Có cách nào để tôi cải thiện hiệu suất CPU/bộ nhớ của chế độ xem này không?

enter image description here

[Cập nhật 1]

dự án mẫu gốc: http://s000.tinyupload.com/index.php?file_id=29810707815310047536

[Cập nhật 2]

tôi đã cố gắng restyling/khuôn mẫu TreeView/TreeViewItems để đến với ví dụ sau. Nó vẫn mất một thời gian dài để bắt đầu/tương tự, sử dụng bộ nhớ cao. Nhưng một khi được nạp, cuộn cảm thấy phản ứng nhanh hơn nhiều so với mẫu ban đầu.

Tự hỏi liệu có cách nào khác để cải thiện hơn nữa thời gian khởi động/sử dụng bộ nhớ không?dự án

restyled TreeView: http://s000.tinyupload.com/index.php?file_id=00117351345725628185

[Cập nhật 2] giải pháp

pushpraj của hoạt động giống như một nét duyên dáng

  • gốc:
    • Startup: 35s,
    • Memory : 393MB
    • Scrolling: Chậm
  • TreeView:
    • Startup: 18s,
    • Memory 377MB,
    • Scrolling: Nhanh
  • pushpraj của giải pháp:
    • Startup : < 1s,
    • Bộ nhớ: 20MB,
    • Scrolling: Nhanh

Trả lời

9

bạn có lẽ có thể giới hạn kích thước tối đa của hộp danh sách rất lớn và cho phép Virtualization

ví dụ

<ListBox MaxHeight="500" 
     VirtualizingPanel.IsVirtualizing="true" 
     VirtualizingPanel.VirtualizationMode="Recycling" /> 

điều này sẽ cho phép ListBox chỉ tải một vài mục và sẽ bật tính năng scro llbar trên hộp danh sách để cuộn đến phần còn lại của các mục nếu cần.

đồng thời thiết lập VirtualizationMode to Recycling sẽ giúp bạn sử dụng lại các mẫu dữ liệu phức tạp, do đó loại bỏ việc tạo lại chúng cho mỗi mục.


EDIT

đây là một giải pháp dựa trên mẫu của bạn, tôi đã sử dụng CompositeCollection với Virtualization để đạt được mong muốn.

XAML

<Grid xmlns:sys="clr-namespace:System;assembly=mscorlib" 
     xmlns:l="clr-namespace:PerfTest"> 
    <Grid.Resources> 
     <DataTemplate DataType="{x:Type l:Permission}"> 
      <StackPanel Orientation="Horizontal"> 
       <CheckBox /> 
       <TextBlock Text="{Binding Name}" /> 
       <Button Content="+" /> 
       <Button Content="-" /> 
       <Button Content="..." /> 
      </StackPanel> 
     </DataTemplate> 
     <CompositeCollection x:Key="data"> 
      <!-- Content 1 --> 
      <TextBlock Text="Title" 
         FontSize="24" 
         FontWeight="Thin" /> 
      <!-- Content 2 --> 
      <TextBlock Text="Subtitle" 
         FontSize="16" 
         FontWeight="Thin" /> 
      <!-- Content 3 --> 
      <CollectionContainer Collection="{Binding DataContext, Source={x:Reference listbox}}" /> 
      <!-- Content 4 --> 
      <TextBlock Text="User must scroll past the entire list box before seeing this" 
         FontSize="16" 
         FontWeight="Thin" 
         Padding="5" 
         TextWrapping="Wrap" 
         Background="#99000000" 
         Foreground="White" /> 
     </CompositeCollection> 
    </Grid.Resources> 
    <ListBox x:Name="listbox" 
      VirtualizingPanel.IsVirtualizing="True" 
      VirtualizingPanel.VirtualizationMode="Recycling" 
      ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
      ItemsSource="{StaticResource data}" /> 
</Grid> 

đang

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     var items = new ObservableCollection<Permission>(); 
     foreach (var i in Enumerable.Range(0, 10000).Select(i => new Permission() { Name = "Permission " + i })) 
     { items.Add(i); } 
     DataContext = items; 
    } 
} 

public class Permission 
{ 
    public string Name { get; set; } 
} 

vì chúng ta không thể tạo ra mẫu dữ liệu cho chuỗi vì vậy tôi đã thay đổi bộ sưu tập chuỗi Permission bộ sưu tập. Tôi hy vọng trong dự án thực sự của bạn nó sẽ là một cái gì đó tương tự.

hãy thử điều này và xem điều này có gần với những gì bạn cần không.

lưu ý: bạn có thể an toàn bỏ qua nếu có bất kỳ cảnh báo nhà thiết kế trên Collection="{Binding DataContext, Source={x:Reference listbox}}"

+0

Sửa chiều cao tối đa của listbox sẽ gây ra 2 thanh cuộn xuất hiện (xem http://i.imgur.com/s1MJ6BO.png?1) – jayars

+1

đúng, nhưng đồng thời ảo hóa chỉ có thể hoạt động khi chiều cao cố định hoặc chiều cao tối đa được xác định, nó không thể hoạt động với chiều cao không giới hạn. Bạn có thể sử dụng bộ sưu tập tổng hợp kết hợp tất cả các mục trong stackpanel và hiển thị tất cả chúng trong một hộp danh sách với kích hoạt ảo hóa. bạn có thể chia sẻ mã, tôi sẽ cố gắng giúp bạn với điều đó. – pushpraj

+0

Đã cập nhật để bao gồm dự án mẫu – jayars

Các vấn đề liên quan