WPF--Datagrid控件 绑定大量数据加载过慢及界面卡顿

一开始我以为时间是花在数据绑定上面,花费很多心思优化,开异步线程,后来才发现是界面渲染,即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”
 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值