DataGridComboboxColumn 的性能问题
Performance issue with a DataGridComboboxColumn
我是 WPF 和 devexpress 的新手,目前正在重新实现一个应用程序。我的目标是删除 WPF 应用程序中对 devexpress 的所有引用,并仅使用 WPF 替换它。
现在我有了这个 DataGridComboBoxColumn,其目的是将员工绑定到 post(例如项目经理)。在这个组合框中有大约 3000 个项目。当应用程序使用 GridControl 时,没有性能问题(在 UI 渲染期间没有减慢速度)。它只是使用 GridControl 和 ComboBoxEdit 作为其中一列的控件模板。
在 WPF 中,我将其替换为:
`<DataGrid x:Name="gridProject" AutoGenerateColumns="False" CanUserAddRows="True"
ItemsSource="{Binding Source={StaticResource ProjectCollectionView}}"
SelectionMode="Single"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
RowHeight="25">
<!-- How to display the person: "NAME FirstName" -->
<DataGrid.Resources>
<DataTemplate x:Key="displayFullNameTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name, Mode=OneWay, IsAsync=True}"></TextBlock>
<TextBlock Text=" "></TextBlock>
<TextBlock Text="{Binding FirstName, Mode=OneWay, IsAsync=True}"></TextBlock>
</StackPanel>
</DataTemplate>
<ItemsPanelTemplate x:Key="virtualizeItemsPanelTemplate">
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</DataGrid.Resources>
<DataGridComboBoxColumn Header="Chief"
SelectedValueBinding="{Binding ChiefReference}"
SelectedValuePath="Matricule"
Width="200">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Source={StaticResource usersList}, Path=Users, IsAsync=True}"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplate}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Source={StaticResource usersList}, Path=Users, IsAsync=True}"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplate}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
<Setter Property="IsEditable" Value="True"/>
<Setter Property="IsTextSearchEnabled" Value="True"/>
<Setter Property="TextSearch.TextPath" Value="Name"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>`
我必须将所有名称显示为 "Name FirstName",并且用户必须能够使用名称在组合框中进行搜索。
由于 Google,我设法解决了一些问题:
- 设置行高和列宽
- 异步加载以在编辑组合框或显示组合框采用的值时显示项目。
- 我虚拟化了组合框和组合框文本块的下拉列表。
- 我启用了行和列虚拟化。
确切的问题如下:在数据网格中导航时滚动时,如果 DataGridComboBoxColumn 在视图中,则滚动变慢。然后,如果我滚动回该列不可见的视图并且它再次流畅。然后,如果我返回此专栏,应用程序需要一些时间(比如 3 秒)来显示组合框的内容。
应用程序中的视图大约有 10 列和 30 行。
所以我认为这个问题与应用程序必须显示 30 个项目并且对于每个项目它必须进行绑定并应用模板以显示我所要求的信息这一事实有关。令我困扰的是使用devexpress绝对没有性能问题。
我是不是做错了什么?我忘记了什么吗?请帮我 :(
提前致谢!
编辑: 我将 .NET 更新到 4.5.2 版本。这样做之后出现了另一个问题:因为我在发送 IsAsync 垃圾邮件,所以我不得不使用委托来填充我的静态资源("user list")。所以现在应用程序在开始加载这个资源(我手工创建的)时需要一些时间。但是问题仍然存在。
我找到了一个不是直接的解决方案。
我没有尝试提高网格性能,而是直接更改了我的数据库。我在我的项目数据库中添加了一个计算列,它是一个字符串 "NAME FirstName".
所以在我的数据网格中,我没有在组合框的元素样式中显示所选值,而是显示了一个标量值。因此在显示时没有什么可在巨大的列表中搜索。
像这样:
<DataGridComboBoxColumn Header="Chief"
Width="200">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding ProjectCollectionView}"/>
<Setter Property="SelectedValue" Value="{Binding ChiefReference, Mode=OneWay}"/>
<Setter Property="SelectedValuePath" Value="ChiefReference"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplateElement}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding usersList IsAsync=True}"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplate}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
<Setter Property="IsEditable" Value="True"/>
<Setter Property="IsTextSearchEnabled" Value="True"/>
<Setter Property="TextSearch.TextPath" Value="Name"/>
<Setter Property="SelectedValue" Value="{Binding ChiefReference}"/>
<Setter Property="SelectedValuePath" Value="ChiefReferenceOfTheUserList"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
现在的问题是,由于元素样式绑定到 属性 而编辑样式绑定到另一个,因此更改组合框的选定值不会更改数据网格的显示值。这是因为我没有动态保存更改,用户必须按 "save" 按钮才能保存更改。因此,这些更改只有在保存更改后才可见,这有点烦人。但这是另一个问题,至少现在的表现还不错。
我是 WPF 和 devexpress 的新手,目前正在重新实现一个应用程序。我的目标是删除 WPF 应用程序中对 devexpress 的所有引用,并仅使用 WPF 替换它。
现在我有了这个 DataGridComboBoxColumn,其目的是将员工绑定到 post(例如项目经理)。在这个组合框中有大约 3000 个项目。当应用程序使用 GridControl 时,没有性能问题(在 UI 渲染期间没有减慢速度)。它只是使用 GridControl 和 ComboBoxEdit 作为其中一列的控件模板。
在 WPF 中,我将其替换为:
`<DataGrid x:Name="gridProject" AutoGenerateColumns="False" CanUserAddRows="True"
ItemsSource="{Binding Source={StaticResource ProjectCollectionView}}"
SelectionMode="Single"
EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
RowHeight="25">
<!-- How to display the person: "NAME FirstName" -->
<DataGrid.Resources>
<DataTemplate x:Key="displayFullNameTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name, Mode=OneWay, IsAsync=True}"></TextBlock>
<TextBlock Text=" "></TextBlock>
<TextBlock Text="{Binding FirstName, Mode=OneWay, IsAsync=True}"></TextBlock>
</StackPanel>
</DataTemplate>
<ItemsPanelTemplate x:Key="virtualizeItemsPanelTemplate">
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</DataGrid.Resources>
<DataGridComboBoxColumn Header="Chief"
SelectedValueBinding="{Binding ChiefReference}"
SelectedValuePath="Matricule"
Width="200">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Source={StaticResource usersList}, Path=Users, IsAsync=True}"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplate}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Source={StaticResource usersList}, Path=Users, IsAsync=True}"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplate}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
<Setter Property="IsEditable" Value="True"/>
<Setter Property="IsTextSearchEnabled" Value="True"/>
<Setter Property="TextSearch.TextPath" Value="Name"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>`
我必须将所有名称显示为 "Name FirstName",并且用户必须能够使用名称在组合框中进行搜索。 由于 Google,我设法解决了一些问题: - 设置行高和列宽 - 异步加载以在编辑组合框或显示组合框采用的值时显示项目。 - 我虚拟化了组合框和组合框文本块的下拉列表。 - 我启用了行和列虚拟化。
确切的问题如下:在数据网格中导航时滚动时,如果 DataGridComboBoxColumn 在视图中,则滚动变慢。然后,如果我滚动回该列不可见的视图并且它再次流畅。然后,如果我返回此专栏,应用程序需要一些时间(比如 3 秒)来显示组合框的内容。
应用程序中的视图大约有 10 列和 30 行。
所以我认为这个问题与应用程序必须显示 30 个项目并且对于每个项目它必须进行绑定并应用模板以显示我所要求的信息这一事实有关。令我困扰的是使用devexpress绝对没有性能问题。
我是不是做错了什么?我忘记了什么吗?请帮我 :( 提前致谢!
编辑: 我将 .NET 更新到 4.5.2 版本。这样做之后出现了另一个问题:因为我在发送 IsAsync 垃圾邮件,所以我不得不使用委托来填充我的静态资源("user list")。所以现在应用程序在开始加载这个资源(我手工创建的)时需要一些时间。但是问题仍然存在。
我找到了一个不是直接的解决方案。
我没有尝试提高网格性能,而是直接更改了我的数据库。我在我的项目数据库中添加了一个计算列,它是一个字符串 "NAME FirstName".
所以在我的数据网格中,我没有在组合框的元素样式中显示所选值,而是显示了一个标量值。因此在显示时没有什么可在巨大的列表中搜索。
像这样:
<DataGridComboBoxColumn Header="Chief"
Width="200">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding ProjectCollectionView}"/>
<Setter Property="SelectedValue" Value="{Binding ChiefReference, Mode=OneWay}"/>
<Setter Property="SelectedValuePath" Value="ChiefReference"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplateElement}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding usersList IsAsync=True}"/>
<Setter Property="ItemTemplate" Value="{StaticResource displayFullNameTemplate}"/>
<Setter Property="ItemsPanel" Value="{StaticResource virtualizeItemsPanelTemplate}"/>
<Setter Property="IsEditable" Value="True"/>
<Setter Property="IsTextSearchEnabled" Value="True"/>
<Setter Property="TextSearch.TextPath" Value="Name"/>
<Setter Property="SelectedValue" Value="{Binding ChiefReference}"/>
<Setter Property="SelectedValuePath" Value="ChiefReferenceOfTheUserList"/>
<Setter Property="IsSynchronizedWithCurrentItem" Value="False"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
现在的问题是,由于元素样式绑定到 属性 而编辑样式绑定到另一个,因此更改组合框的选定值不会更改数据网格的显示值。这是因为我没有动态保存更改,用户必须按 "save" 按钮才能保存更改。因此,这些更改只有在保存更改后才可见,这有点烦人。但这是另一个问题,至少现在的表现还不错。