当我尝试使用可编辑的多行TextBoxes来实现Grouped ListView时遇到此问题:当尝试在TextBox中键入并更改行(按Enter或text需要换行)并且键入TextBox的高度增加导致ListViewItem(行),那么UI线程性能似乎会变慢。
当相当多的组中每个组具有不同数量的项目(从0到5)时,并且每个文本都包含多行内容,这种UI性能的障碍就更加明显。
在以下情况下,该问题消失了:
ListView未分组
ListView虚拟化被覆盖(通过使用StackPanel而不是ItemsStackPanel作为ItemsPanelTemplate),但是我失去了虚拟化的加载性能优势和Group头良好的粘性行为。
要填充ListView,我使用模型绑定。这是我使用的代码:
这是一个虚拟模型,用于保存可编辑文本框和MyModel的集合对象的数据,以生成具有CollectionName属性的组以显示为组头。
public class MyModel
{
public string Cell1 { get; set; }
public string Cell2 { get; set; }
public string Cell3 { get; set; }
}
public class MyModelCollection : Collection<MyModel>
{
public string CollectionName { get; set; }
}
然后使用ViewModel填充数据以在View中显示:您可以注意到我生成的组包含0到5个项目(行)。每行应包含三个多行文本框(单元格)。
public class MainPageViewModel
{
public List<MyModelCollection> MyModelCollections { get; set; }
public MainPageViewModel()
{
var myCollections = new List<MyModelCollection>();
for (var j = 0; j < 20; j++)
{
var myCollection = new MyModelCollection();
myCollection.CollectionName = "Title of group " + j;
var iMax = 5;
if (j == 0|| j == 5 || j == 6 || j == 9 || j == 11) iMax = 0;
if (j == 3 || j == 7 || j == 8) iMax = 1;
if (j == 2 || j == 10) iMax = 3;
for (var i = 0; i < iMax; i++)
{
var row = new MyModel();
var multiLine1 = new StringBuilder();
multiLine1.AppendLine("Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1Line1Line1Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 Line1 ");
multiLine1.AppendLine("Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2Line2Line2 Line2 Line2Line2 Line2Line2 Line2 Line2 Line2 Line2 Line2 Line2Line2 Line2 Line2 Line2 Line2Line2 Line2 Line2 Line2 Line2");
row.Cell1 = multiLine1.ToString();
var multiLine2 = new StringBuilder();
multiLine2.AppendLine("Line1");
multiLine2.AppendLine("Line2Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2Line2Line2 Line2 Line2Line2 Line2Line2 Line2 Line2 Line2 Line2 Line2 Line2Line2 Line2 Line2 Line2 Line2Line2 Line2 Line2 Line2 Line2");
multiLine2.AppendLine("Line3");
multiLine2.AppendLine("Line4");
row.Cell2 = multiLine2.ToString();
var multiLine3 = new StringBuilder();
multiLine3.AppendLine("Line1");
multiLine3.AppendLine("Line2Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2 Line2Line2Line2 Line2 Line2Line2 Line2Line2 Line2 Line2 Line2 Line2 Line2 Line2Line2 Line2 Line2 Line2 Line2Line2 Line2 Line2 Line2 Line2");
multiLine3.AppendLine("Line3 Line3 Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3Line3 Line3");
row.Cell3 = multiLine3.ToString();
myCollection.Add(row);
}
myCollections.Add(myCollection);
}
MyModelCollections = myCollections;
}
}
然后将MainPageViewModel设置为XAML页面的DataContext(名为ViewModel)
<Page.DataContext>
<local:MainPageViewModel x:Name="ViewModel"/>
</Page.DataContext>
然后使用XAML页面资源中的CollectionViewSource启用绑定:
<Page.Resources>
<CollectionViewSource x:Key="CollectionsSource" IsSourceGrouped="True" Source="{x:Bind ViewModel.MyModelCollections, Mode=OneWay}"></CollectionViewSource>
</Page.Resources>
最后是XAML视图中的ListView控件
<ListView ItemsSource="{Binding Source={StaticResource CollectionsSource}}">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="False" >
<GroupStyle.HeaderTemplate>
<DataTemplate x:DataType="local:MyModelCollection">
<Grid>
<TextBlock Text="{x:Bind CollectionName}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:MyModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Text="{x:Bind Cell1, Mode=TwoWay}" TextWrapping="Wrap" BorderThickness="0" Grid.Column="0" AcceptsReturn="True"/>
<TextBox Text="{x:Bind Cell2, Mode=TwoWay}" TextWrapping="Wrap" BorderThickness="0" Grid.Column="1" AcceptsReturn="True"/>
<TextBox Text="{x:Bind Cell3, Mode=TwoWay}" TextWrapping="Wrap" BorderThickness="0" Grid.Column="2" AcceptsReturn="True"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
在尝试运行上述代码时,如果我向下滚动到第4组的最后一项(屏幕下方显示了第5,6和7组),并尝试在第一个单元格中写入,导致该项目的高度达到增加,则UI的性能很差。在其他一些打字情况下,这种性能障碍并不明显,您可以尝试...
如前所述,性能问题消失了:
或者我通过使用普通StackPanel作为ItemsPanelTemplate来删除ListView虚拟化(请参见下面的新ListView xaml)
<ListView ItemsSource="{Binding Source={StaticResource CollectionsSource}}">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="False" >
<GroupStyle.HeaderTemplate>
<DataTemplate x:DataType="local:MyModelCollection">
<Grid >
<TextBlock Text="{x:Bind CollectionName}"/>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:MyModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Text="{x:Bind Cell1, Mode=TwoWay}" TextWrapping="Wrap" BorderThickness="0" Grid.Column="0" AcceptsReturn="True"/>
<TextBox Text="{x:Bind Cell2, Mode=TwoWay}" TextWrapping="Wrap" BorderThickness="0" Grid.Column="1" AcceptsReturn="True"/>
<TextBox Text="{x:Bind Cell3, Mode=TwoWay}" TextWrapping="Wrap" BorderThickness="0" Grid.Column="2" AcceptsReturn="True"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>