2015-11-05 263 views
1

我用MVVM构建一个WPF应用程序;其中一个视图包含一个长度在200-500之间的模型集合,每个模型都映射到RepositoryViewModel并绑定到堆栈面板中的“Repository.xaml”视图。WPF UI线程阻塞与大集合

顶层视图(Main.xaml)如下:

<Window.Resources> 
    <DataTemplate DataType="{x:Type home:RepositoryViewModel}"> 
     <vw:Repository /> 
    </DataTemplate> 
<Window.Resources> 
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Margin="5 40 5 5"> 
    <StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True"> 
     <ItemsControl ItemsSource="{Binding Repositories}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <WrapPanel Orientation="Horizontal" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ItemsControl> 
    </StackPanel> 
</ScrollViewer> 

Repository.xaml用户控件如下:

<Grid Margin="5" Visibility="{Binding Model.Visibility}" > 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition SharedSizeGroup="WrapPanelGroup" /> 
     <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions> 

    <StackPanel Grid.Column="1">  
     <!--Textbox is used to allow user to select the text. Changing to Label does not help with rendering issues-->  
     <TextBox Background="Transparent" BorderThickness="0" Text="{Binding Model.Name}" IsReadOnly="True" 
       TextWrapping="Wrap" FontSize="18" MaxWidth="300" /> 
     <TextBox Background="Transparent" BorderThickness="0" Text="{Binding Model.Url}" IsReadOnly="True" 
       TextWrapping="Wrap" FontSize="8" MaxWidth="300" Foreground="DarkGray" /> 
    </StackPanel> 
    <Button Grid.Column="2" Content="Checkout" Command="{Binding CheckoutCommand}" Visibility="{Binding Model.SingleCheckoutVisible}"/> 
    <CheckBox Grid.Column="2" IsChecked="{Binding Model.IsChecked}" Visibility="{Binding Model.BulkCheckoutVisible}"/> 
</Grid> 

上述作品完美,因为我需要,问题是时间WPF花费一旦渲染控制 - 每个RepositoryViewModel的被添加到RepositoryViewModelObservableCollection而对照3-5秒整个UI冻结被渲染的。

虽然试图孤立我注意到,通过删除文本框的渲染时间急剧下降,但去除问题上的文本框的结合并没有做出明显的差异。交换标签的文本框几乎没有区别。

是集大小仅仅是大的期望WPF能够快速处理还是我失去的东西,增加了渲染时间?我确实认为有MaxWidth的SharedSizeGroup可能是罪魁祸首,但删除不会提高性能。

谢谢。

+0

更新:主要元凶增加渲染时间是因为我不得不对WrapPanel内的每个用户控制一个动态高度&宽度,设定一个固定的高度/宽度显着增加渲染时间。 – Anth12

回答

2

查找到加入虚拟化你的ItemsControl。这样它只能渲染视图中的项目而不是全部。

<ItemsControl VirtualizingStackPanel.IsVirtualizing="True" 
       ScrollViewer.CanContentScroll="True"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

我相信你想也需要从StackPanel中和ScrollViewer中取出ItemsControl的,因为他们会给ItemsControl的无限空间来呈现,并呈现虚拟化无用。

我看到你正在为你的ItemsPanelTemplate使用一个WrapPanel,因此你可能需要推出你自己的虚拟化面板,或者查看一些othercontrols(这些我自己没有使用过)。

+1

另外不要忘记在运行时使用WPF树可视化工具来查看控件,以确认虚拟化实际上是否正常工作,它有一个很容易破坏的恶习。 –

+0

谢谢,我会做一些关于虚拟化的研究。我忘了提及还有一个搜索将'Model.Visibility'的值(在Repository.xaml中使用)设置为可见或折叠状态,但我认为它在虚拟化中受支持? – Anth12

+1

意思是你基本上希望根据不同的条件过滤掉某些项目的视图?看看将你的ItemsControl绑定到一个CollectionViewSource。这可以处理你想呈现视图的所有不同方式,包括排序和过滤。 – WasGoodDone