我正在使用ListView,它的View设置为GridView,以显示动态生成的列中的项目。 ListView的虚拟化已启用。对于此示例,我想显示最多10行,每列50列(但列数是动态的)。
我要做的第一件事就是在循环中创建代码中的列。 “Items”只是我的视图模型中一行的ObservableCollection字符串。
int index = 0;
foreach(Header header in Headers)
{
GridViewColumn column = new GridViewColumn();
column.Header = // the view model of the header;
column.HeaderTemplate = Resources["HeaderTemplate"] as DataTemplate;
column.DisplayMemberBinding = new Binding("Items" + "[" + index + "]");
m_MyGridView.Columns.Add(column);
index++;
}
现在,当我更改ListView的ItemsSource时,数据会快速安静地更新。
不幸的是,每个单元格中的每个字符串都必须格式化(字体颜色,前景等)。所以我不能使用DisplayMemberBinding,而是使用CellTemplate为每个单元格分配一个DataTemplate。
为此,我在我的控件中的xaml中创建了一个DataTemplate,它包含ListView。它只包含一个TextBlock,其中包含一些与单元视图模型属性的绑定,以定义TextBlock的字符串样式。 现在,Items不仅仅是一个字符串集合,而是一个CellViewModel集合,它不仅包含要显示的值,还包含如何显示它的信息。然后,此信息将绑定在DataTemplate中。
CellTemplate在代码中设置并分配给每个GridViewColumn的CellTemplate:
foreach(Header header in Headers)
{
GridViewColumn column = new GridViewColumn();
column.Header = // the view model of the header;
column.HeaderTemplate = Resources["HeaderTemplate"] as DataTemplate;
column.CellTemplate = createCellTemplate(index);
m_MyGridView.Columns.Add(column);
index++;
}
DataTemplate getCellTemplate(int index)
{
FrameworkElementFactory elementFactory = new FrameworkElementFactory (typeof (ContentControl));
elementFactory.SetBinding(ContentControl.ContentProperty, new Binding("Items" + "[" + index + "]"));
DataTemplate dt = Resources["ValueTemplate"] as DataTemplate;
elementFactory.SetValue(ContentControl.ContentTemplateProperty, dt);
DataTemplate dataTemplate = new DataTemplate ();
dataTemplate.VisualTree = elementFactory;
return dataTemplate;
}
当我这样做时,当我更改ListView的ItemsSource时,事情变得非常缓慢。现在每次更改ItemsSource以显示不同数据时,现在需要将近一秒的时间来渲染新单元格。
那么有没有办法加快速度?我想通过使用Paragraph将格式化的字符串放在我的CellViewModel中,但不幸的是DisplayMemberBinding只支持字符串,所以我必须使用CellTemplate。
编辑:所以,这是我正在使用的列表视图:
<ListView ItemsSource="{Binding ElementName=Control, Path=ItemViewModels}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" VirtualizingStackPanel.IsVirtualizing="True" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.View>
<GridView x:Name="m_MyGridView"/>
</ListView.View>
</ListView>
和单元格的DataTemplate:
<DataTemplate x:Key="ValueTemplate">
<Border Background="{Binding Path=BackgroundColor">
<TextBlock Text="{Binding Path=Value}"
Foreground="{Binding Path=ForegroundColor}"
FontStyle="{Binding Path=FontStyle}"
FontWeight="{Binding Path=FontWeight}"
</TextBlock>
</Border>
</DataTemplate>
创建标题时,只调用一次getCellTemplate函数。当ItemsSource更改时,它不会被调用,因为它们已经创建。