WPF 自定义的图表(适用大量数据绘制)下

本文介绍了如何优化WPF中大量数据图表的绘制,通过将数据显示与图表分离、动态调整绘制频率及利用START_INDEX和END_INDEX来改善性能。通过这些方法,即便数据量达到10W,也能保证界面流畅地显示数据。
摘要由CSDN通过智能技术生成
上一篇文章中讲了WPF中自定义绘制大量数据的图标,思路是先将其绘制在内存,然后一次性加载到界面,在后续的调试过程中,发现当数据量到达10W时,移动鼠标显示数据有明显的延迟。经过思考,我采用了以下两个办法解决这个问题:
1.将数据显示的文本与图表分离,作为一个单独的canvas,这样,显示文本数据的时候就不需要重画图表了
2.计算鼠标移动速度,当移动速度过快时,不绘制文本,减少数据文本的绘制频率
3.使用START_INDEX 和 END_INDEX来表示绘制数据的其实位置和结束位置,减少对整个数据的遍历

首先看前台代码
<UserControl x:Class="Zero_Gjy.UserControls.DrawChart"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Zero_Gjy.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <ScrollViewer >

        <Grid x:Name="linechart" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">

        </Grid>
    </ScrollViewer>
</UserControl>
在lineChart中分别加入图表的Canvas和文本数据的Canvas,修改之前的DrawingCanvas,把绘制数据文本的代码分离出来
DrawingCanvas.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;

namespace Zero_Gjy.UserControls
{
    public class DrawingCanvas : Canvas
    {
        private List<Visual> visuals = new List<Visual>();

        public const double YZero = 50;
        public const double YMargin = 50;
        private double YLabelLen = 5;
        private double yHeight;
        private Brush line1Color = Brushes.Black;
        private Brush labelColor = Brushes.Black;
        private Brush axisColor = Brushes.Black;
        private Brush line2Color = Brushes.Black;
        private double thinkness = 1;
        private double canvasWidth = 0;
        private double xWidth;
        private const int yLinesCount = 12;

        List<LineDatas> allDatas;
        private double canvasHeight;
        int dataCount = 0;
        int rtCount = 0;
        public enum MouseMode
        {
            ZOOM,
            VIEW
        }
        public MouseMode mMode = MouseMode.VIEW;
        public DrawingCanvas()
        {
            this.Background = Brushes.Transparent;
            this.HorizontalAlignment = HorizontalAlignment.Left;
            this.VerticalAlignment = VerticalAlignment.Top;
            this.Margin = new Thickness(0, 0, 0, YMargin);
            AllDatas = new List<LineDatas>();
           
        }

        //获取Visual的个数
        protected override int VisualChildrenCount
        {
            get { return visuals.Count; }
        }
       
        //获取Visual
        protected override Visual GetVisualChild(int index)
        {
            return visuals[index];
        }
        
        //添加Visual
        public void AddVisual(Visual visual)
        {
            visuals.Add(visual);

            base.AddVisualChild(visual);
            base.AddLogicalChild(visual);
        }

        //删除Visual
        public void RemoveVisual(Visual visual)
        {
            visuals.Remove(visual);

            base.RemoveVisualChild(visual);
            base.RemoveLogicalChild(visual);
        }

        //命中测试
        public DrawingVisual GetVisual(Point point)
        {
            HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
            return hitResult.VisualHit as DrawingVisual;
        }
        
        //使用DrawVisual画Polyline
        //DrawingVisual lineVisual;
        public void addData(string title,double min,double max,DoubleCollection xData, DoubleCollection mData, DoubleCollection sData)
        {
            AllDatas.Add(new LineDatas(title, min, max, xData,mData, sData));
            
            dataCount++;
            rtCount = mData.Count;
        }
        public void removeFirst() {
            for(int i = 0; i < AllDatas.Count; i++)
            {
                AllDatas[i].RtData.RemoveAt(0);
                AllDatas[i].ThData.RemoveAt(0);               
            }           
        }
        public void removeLast()
        {
            for (int i = 0; i < AllDatas.Count; i++)
            {
                AllDatas[i].RtData.RemoveAt(AllDatas[i].RtData.Count - 1);
                AllDatas[i].ThData.RemoveAt(AllDatas[i].ThData.Count - 1);
            }
        }
        /// <summary>
        /// 添加数据点
        /// </summary>
        /// <param name="xdatas">x坐标</param>
        /// <param name="rtdatas">实测数据</param>
        /// <param name="thdatas">理论数据</param>
        public void addPoint(double[] xdatas,double[] rtdatas,double[] thdatas)
        {
            if (rtdatas.Length != allDatas.Count)
                throw new Exception() { Source="数据个数不匹配"};       
            for (int i = 0; i < allDatas.Count; i++)
            {
                AllDatas[i].XData.Insert(0, xdatas[i]);
                AllDatas[i].RtData.Insert(0,rtdatas[i]);
                AllDatas[i].ThData.Insert(0,thdatas[i]);
                if (allDatas[i].Min > rtdatas[i])
                    allDatas[i].Min = rtdatas[i];
                if (allDatas[i].Max < rtdatas[i])
                    allDatas[i].Max = rtdatas[i];
            }
        }
        //清空所有数据
     
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值