2012-03-06 1 views
1

관찰 가능한 개체 목록에 바인딩 된 DataGrid가 있습니다. ItemsControl이 해당 목록에 바인딩되어 있으면 (DataGrid 헤더를 클릭하여) 정렬 성능이 매우 낮습니다 (아래 샘플의 경우 몇 초 정도). ItemsControl이 같은 목록에 바인딩되어 있지 않으면 정렬은 즉시입니다. 여기 ItemsControl도 동일한 ItemsSource에 바인딩하는 경우 DataGrid 정렬이 매우 느립니다.

이 동작을

namespace LargeDataGridViewTest 
{ 
    public partial class MainWindow 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new MainPresenter(); 
     } 
    } 

    public class MainPresenter : INotifyPropertyChanged 
    { 
     private readonly ObservableCollection<Item> _items = new ObservableCollection<Item>(); 
     public IEnumerable<Item> Items { get { return _items; } } 

     public MainPresenter() 
     { 
      for (var i = 0; i < 10000; i++) 
       _items.Add(new Item()); 
     } 
    } 

    public class Item : INotifyPropertyChanged 
    { 
     public int Random { get; private set; } 
     private static readonly Random Rand = new Random(); 

     public Item() 
     { 
      Random = Rand.Next(0, 1000000); 
     } 
    } 
} 

을 나타내는 몇 가지 예제 코드와 해당 XAML

<Window.Resources> 
    <DataTemplate DataType="{x:Type LargeDataGridViewTest:MainPresenter}"> 
     <DockPanel> 
      <DataGrid ItemsSource="{Binding Items}"/> 
      <!--ListBox ItemsSource="{Binding Items}"/--> 
      <ItemsControl ItemsSource="{Binding Items}"/> 
     </DockPanel> 
    </DataTemplate> 
</Window.Resources> 

<ContentPresenter Content="{Binding}"/> 

대신 ItemsControl에의 나는 목록 상자를 사용하는 경우, 정렬 성능이 괜찮이다. ListBox를 사용하지만 ItemsPanelTemplate을 변경하여 기본 ItemsControl에 액세스하면 성능이 나 빠지게됩니다.

(동일한 항목을 참조하는) 목록의 단순 복사본을 가져 와서 대신 ItemsControl을 바인딩하면 성능이 좋습니다.

속도가 느린 ItemsControl 바인딩과 EQATEC 프로파일 러를 통한 빠른 ListBox 바인딩을 모두 실행하면 최상위 수준의 앱 시간 이외의 성능에는 차이가 없습니다.

여기에 무슨 일이 일어나는 지 아는 사람이 있습니까? 대답의

편집

일부는 ItemsControls는 가상화 따라서 단지 눈에 보이는 것보다는 모든 항목을 그릴 필요가 있지 않은지 것으로 보인다. 이 경우 ItemsControl 바인딩 모드가 OneTime 인 경우에도 DataGrid가 정렬 될 때 모든 ItemsControl 항목이 다시 그려지는 이유는 무엇입니까? 그리고 DataGrid 정렬의 성능에 영향을주는 것을 어떻게 막을 수 있습니까?

답변

0

DataGridListBox은 기본적으로 항목을 가상화하고 ItemsControl은 가상화하지 않기 때문에 그럴 것으로 생각됩니다.

즉, DataGridListBox은 화면에 표시되는 UI 개체 만 만들고 ItemsControl은 10,000 개의 UI 개체를 모두 만듭니다.

성능을 수정하려면 virtualize your ItemsControl. 필요한 세부 정보는 링크 된 질문을 통해 확인하십시오.

<ItemsControl 
    VirtualizingStackPanel.IsVirtualizing="True" <!-- needed --> 
    ScrollViewer.CanContentScroll="True" <!-- needed --> 
    ... > 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel /> <!-- needed --> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.Template> 
     <ControlTemplate> 
      <ScrollViewer> <!-- needed --> 
       <ItemsPresenter /> 
      </ScrollViewer> 
     </ControlTemplate> 
    </ItemsControl.Template> 
</ItemsControl> 
+0

그러면 ItemsPanelTemplate을 변경할 때 ListBox의 가상화가 손실됩니다. – Scroog1

+0

@ Scroog1 나는 그렇게 생각하지 않는다. 가상화는'ControlTemplate'의 일부이기 때문에'ItemsPanelTemplate'을 변경해도 영향을 미치지 않습니다. – Rachel

+0

그러나 위 예제를 ItemsPanelTemplate (예 : )의 ListBox로 변경하면 정렬 성능이 다시 떨어집니다. – Scroog1

0

가상화가 핵심입니다!

ItemsControls는 기본적으로 가상화되지 않으며 데이터 격자가 Items 컬렉션을 정렬하면 기본 컬렉션보기가 정렬되고 다른 컬렉션에도 동일한 정렬이 적용됩니다. ItemsControl 그러나 ItemsControl에는 구현 된 가상화가 없으므로 항목을 정렬 할뿐만 아니라 항목 컨테이너에도 렌더링합니다. ListBox은 가상화가 기본적으로 구현되어 있기 때문에 성능이 향상됩니다.

이 경우 빠른 수정은 ItemsControl처럼 보이는 ListBox을 시뮬레이트합니다. 목록 상자의 선택 색상을 제거하면됩니다.

<ListBox ItemsSource="{StaticResource MyData}" DisplayMemberPath="ID"> 
     <ListBox.ItemContainerStyle> 
      <Style TargetType="{x:Type ListBoxItem}"> 
       <Style.Resources> 
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
            Color="Transparent"/> 
       </Style.Resources> 
       <Style.Triggers> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="Foreground" Value="Black"/> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
     </ListBox.ItemContainerStyle> 
    </ListBox> 
관련 문제