一开始我以为时间是花在数据绑定上面,花费很多心思优化,开异步线程,后来才发现是界面渲染,即DataGrid绑定数据后,界面呈现花了很多时间。
虚拟化的作用:假设DataGrid.ItemSource绑定的数据源有5000条数据,窗体大小只能显示40条数据,那么它就会先只实例化这40条数据呈现出来。如果没有实例化,那它会把5000条全部实例化呈现出来。
虚拟化的缺点:没有实例化的部分无法获取。
1、前台xaml
<ScrollViewer Name="scrollviewLog" Width="480" Height="250" Margin="5">
<DataGrid Name="dataGrid" ItemsSource="{Binding MessageCollection,Mode=OneWay}" Style="{StaticResource dataGridStyleLog}" BorderBrush="#17aeec"
BorderThickness="1" VirtualizingPanel.IsContainerVirtualizable="True" VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling">
<DataGrid.Columns>
<DataGridTextColumn Header="{DynamicResource 日志}" Binding="{Binding Message}" Width="auto"/>
<DataGridTextColumn Header="{DynamicResource 时间}" Binding="{Binding MessageDate}" Width="200"/>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
2、MVVM框架 View Model
private AsyncObservableCollection<MessageModel> messageCollection = new AsyncObservableCollection<MessageModel>();
/// 所有消息集合
/// <summary>
/// 所有消息集合
/// </summary>
public AsyncObservableCollection<MessageModel> MessageCollection {
get {
return messageCollection;
}
}
3、窗体初始化
public MessageBoxWindow()
{
InitializeComponent();
dataGrid.DataContext = MessageVM.Instance;
MessageVM.Instance.MessageCollection.CollectionChanged -= MessageCollection_CollectionChanged;
MessageVM.Instance.MessageCollection.CollectionChanged += MessageCollection_CollectionChanged;
MessageVM.Instance.MessagaeBoxWindowClosed = false;
}
按道理虚拟化可以提高datagrid 界面渲染性能,但是我发现完全不起作用,后来发现外层套的滚动条导致虚拟化没有产生作用,这个滚动条是为了添加日志时,实时滚动到最后一条。这个完全可以用datagrid自带的滚动条做。
修改后前台xaml:
<DataGrid Name="dataGrid" ItemsSource="{Binding MessageCollection,Mode=OneWay,IsAsync=True}"
Style="{StaticResource dataGridStyleLog}" BorderBrush="#17aeec" Margin="5"
BorderThickness="1" EnableColumnVirtualization="True" EnableRowVirtualization="True">
<DataGrid.Columns>
<DataGridTextColumn Header="{DynamicResource 日志}" Binding="{Binding Message}" Width="auto"/>
<DataGridTextColumn Header="{DynamicResource 时间}" Binding="{Binding MessageDate}" Width="200"/>
</DataGrid.Columns>
</DataGrid>
注意两个虚拟化属性
后台滚动条效果:
void MessageCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
try
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
dataGrid.ScrollIntoView(dataGrid.Items[MessageVM.Instance.MessageCollection.Count - 1]);
}
}
catch { }
}
我的目的是查询一张表,然后把结果显示在DataGrid中,结果发现仅有一两百条数据就会阻塞UI进程2~3秒,找资料后有以下几点思路解决。
DataGrid是否嵌入在StackPanel或ScrollView中?若是,删掉上述两种容器,直接使用DataGrid作为最外层控件。
是否频繁动态调整每一行数据的列宽?若是,改用auto或*或固定值定义列宽。
控件样式对性能的影响?有可能样式太过复杂的话也会对刷UI的速度造成影响。
尝试为DataGrid设置VirtualizingStackPanel.IsVirtualizing =“true”