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

上一篇文章中讲了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];
            }
        }
        //清空所有数据
        public void clearData()
        {
            AllDatas.Clear();

        }
        //将数据清零
        public void cleanData()
        {
            foreach(LineDatas item in allDatas)
            {
                for(int i = 0; i < item.RtData.Count; i++)
                {
                    item.RtData[i] = 0;
                    item.ThData[i] = 0;
                }
                item.Min = -1;
                item.Max = 1;
            }
        }
        public void Polyline()
        {
            //如果虚画布没有数据
            if(this.visuals.Count == 0)
            {
                for(int i = 0; i < AllDatas.Count; i++)
                {
                    this.visuals.Add(new DrawingVisual());
                }
            }
            for(int count = 0; count < AllDatas.Count; count++){
                //计算基础坐标系
                double x0, y0;
                x0 = YZero;
                y0 = (count + 1) * YMargin + count * yHeight;
                string title = AllDatas[count].Title;

                LineDatas datas = allDatas[count];
                DrawingVisual lineVisual = (DrawingVisual)this.visuals[count];
                DrawingContext dc = lineVisual.RenderOpen();
                Pen penAxis = new Pen(AxisColor, Thinkness);
                penAxis.Freeze();

                int yLabelMax = (int)AllDatas[count].Max + 1;
                int yLabelMin = (int)AllDatas[count].Min - 1;
                //画标题
                FormattedText fttitle = new FormattedText(title, new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 15, Brushes.Black);
                dc.DrawText(fttitle, new Point(xWidth / 2+x0 - fttitle.Width / 2, y0 - fttitle.Height));
                //画Y轴
                dc.DrawLine(penAxis, new Point(x0, y0), new Point(x0, y0 + yHeight));
                dc.DrawLine(penAxis, new Point(x0 - YLabelLen, y0), new Point(x0, y0));
                dc.DrawLine(penAxis, new Point(x0 - YLabelLen, y0 + yHeight / 2), new Point(x0, y0 + yHeight / 2));
                dc.DrawLine(penAxis, new Point(x0 - YLabelLen, y0 + yHeight), new Point(x0, y0 + yHeight));
                //y轴文本
                FormattedText ft1 = new FormattedText(yLabelMax.ToString(), new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 10, Brushes.Black);
                dc.DrawText(ft1, new Point(x0 - YLabelLen - ft1.Width, y0 - ft1.Height / 2));
                FormattedText ft2 = new FormattedText(((yLabelMax + yLabelMin) / 2).ToString(), new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 10, Brushes.Black);
                dc.DrawText(ft2, new Point(x0 - YLabelLen - ft2.Width, y0 + YHeight / 2 - ft2.Height / 2));
                FormattedText ft3 = new FormattedText(yLabelMin.ToString(), new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 10, Brushes.Black);
                dc.DrawText(ft3, new Point(x0 - YLabelLen - ft3.Width, y0 + yHeight - ft3.Height / 2));
                //画线
                Pen linePen1 = new Pen(Line1Color, Thinkness);
                linePen1.Freeze();
                Pen linePen2 = new Pen(Line2Color, Thinkness);
                linePen2.Freeze();
                double ratio = (yLabelMax - yLabelMin) / yHeight;
                double step = xWidth / (datas.EndIndex - datas.StartIndex +1);
                //Console.WriteLine("=======datastep:" + step);
                for (int i = datas.StartIndex; i < datas.EndIndex; i++)
                {
                    //将数值转换成位置
                    //理论值
                    Point p3 = new Point(x0 + (i - datas.StartIndex)*step, y0 + (yLabelMax - datas.ThData[i]) / ratio);
                    Point p4 = new Point(x0 + (i - datas.StartIndex + 1)*step, y0 + (yLabelMax - datas.ThData[i + 1]) / ratio);
                    dc.DrawLine(linePen2, p3, p4);
                    //实测值
                    Point p1 = new Point(x0 +(i - datas.StartIndex) *step, y0 + (yLabelMax - datas.RtData[i]) / ratio);
                    Point p2 = new Point(x0 + (i - datas.StartIndex + 1)*step, y0 + (yLabelMax - datas.RtData[i + 1]) / ratio);
                    dc.DrawLine(linePen1, p1, p2);
                }
                //绘制纵向网格和x轴文本
                Pen pen3 = new Pen(new SolidColorBrush((Color)ColorConverter.ConvertFromString("#666666")), 1);
                pen3.DashStyle = new DashStyle(new double[] { 2.5, 2.5 }, 0);
                pen3.Freeze();
                double stepX = xWidth / yLinesCount;
                int stepData = (datas.EndIndex - datas.StartIndex + 1) / yLinesCount;
                if (stepData < 1)
                    stepData = 1;
                for (int i = 1; i < yLinesCount; i++)
                {
                    //纵向网格
                    Point p1 = new Point(x0 + i * stepX, y0 + yHeight);
                    Point p2 = new Point(x0 + i * stepX, y0);
                    dc.DrawLine(pen3, p1, p2);
                    //x轴文本
                    FormattedText ftX = new FormattedText(datas.XData[i * stepData].ToString(), new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 10, Brushes.Black);
                    Point p3 = new Point(x0 + i * stepX - ftX.Width / 2, yHeight + y0);
                    dc.DrawText(ftX, p3);
                }
                dc.Close();
            }
            this.InvalidateVisual();
        }

        public double YHeight
        {
            get
            {
                return yHeight;
            }

            set
            {
                yHeight = value;
            }
        }

        public Brush LabelColor
        {
            get
            {
                return labelColor;
            }

            set
            {
                labelColor = value;
            }
        }

        public Brush AxisColor
        {
            get
            {
                return axisColor;
            }

            set
            {
                axisColor = value;
            }
        }

        public double Thinkness
        {
            get
            {
                return thinkness;
            }

            set
            {
                thinkness = value;
            }
        }       

        public static double YZero1
        {
            get
            {
                return YZero;
            }
        }

        public double CanvasWidth
        {
            get
            {
                return canvasWidth;
            }

            set
            {
                canvasWidth = value;
                this.Width = value;
                xWidth = value - YMargin - YZero;
            }
        }

        public Brush Line2Color
        {
            get
            {
                return line2Color;
            }

            set
            {
                line2Color = value;
            }
        }

        public Brush Line1Color
        {
            get
            {
                return line1Color;
            }

            set
            {
                line1Color = value;
            }
        }

        public double CanvasHeight
        {
            get
            {
                return canvasHeight;
            }

            set
            {
                canvasHeight = value;
            }
        }

        public int DataCount
        {
            get
            {
                return dataCount;
            }

            set
            {
                dataCount = value;
            }
        }

        public int RtCount
        {
            get
            {
                return rtCount;
            }

            set
            {
                rtCount = value;
            }
        }

        internal List<LineDatas> AllDatas
        {
            get
            {
                return allDatas;
            }

            set
            {
                allDatas = value;
            }
        }
    }
}

DrawingLine.CS

using System;
using System.Collections.Generic;
using System.Diagnostics;
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
{
    class DrawingLine : Canvas
    {
        private List<Visual> visuals = new List<Visual>();
        DrawingCanvas drawingCanvas;
        private double x0;
        private double y0;
        private double mWidth;
        private double mHeight;
        public enum MouseMode
        {
            ZOOM,
            VIEW
        }
        public MouseMode mMode = MouseMode.VIEW;
        private double canvasWidth;
        public DrawingLine(DrawingCanvas _dc)
        {
            this.drawingCanvas = _dc;
            this.Background = Brushes.Transparent;
            this.HorizontalAlignment = HorizontalAlignment.Left;
            this.VerticalAlignment = VerticalAlignment.Top;
            this.Height = drawingCanvas.CanvasHeight;
            this.Width = drawingCanvas.CanvasWidth;

            x0 = DrawingCanvas.YZero;
            y0 = DrawingCanvas.YMargin;

            mHeight = _dc.AllDatas.Count * (DrawingCanvas.YMargin + _dc.YHeight);

            this.PreviewMouseLeftButtonDown += DrawingCanvas_MouseLeftButtonDown;
            this.PreviewMouseLeftButtonUp += DrawingCanvas_MouseLeftButtonUp;
            this.MouseMove += DrawingCanvas_MouseMove;
            this.MouseLeave += DrawingCanvas_MouseLeave;
        }
        //鼠标离开画布
        private void DrawingCanvas_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (mMode == MouseMode.VIEW)
            {
                this.RemoveVisual(textVisual);
                this.InvalidateVisual();
            }
        }
        //选中放大区域完成,显示放大区域
        private void DrawingCanvas_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            isMouseDown = false;
            mMode = MouseMode.VIEW;
            endup = e.GetPosition(this).X;
            if (endup < x0)
                endup = x0;
            if (endup > x0+mWidth)
                endup = x0 + mWidth;
            //重画 选中区域
            int len = drawingCanvas.AllDatas[0].EndIndex - drawingCanvas.AllDatas[0].StartIndex+1;
            if (drawingCanvas.AllDatas.Count < 1 || len < 1)
                return;
            double step = mWidth / len;
            if (isMouseMoved && Math.Abs(endup - startDown) > step)
            {
                int startIndex = 0;
                int endIndex = 0;
                if (endup > startDown)
                {
                    startIndex = (int)((startDown - x0) / step) + 1;
                    endIndex = (int)((endup - x0) / step);
                }
                else
                {
                    startIndex = (int)((endup - x0) / step) + 1;
                    endIndex = (int)((startDown - x0) / step);
                }

                foreach (LineDatas data in drawingCanvas.AllDatas)
                {
                    data.EndIndex = data.StartIndex + endIndex;
                    data.StartIndex = data.StartIndex + startIndex;
                }
                drawingCanvas.Polyline();
                this.RemoveVisual(rectVisual);
                this.InvalidateVisual();
            }
            isMouseMoved = false;
        }
        double preMoved = DrawingCanvas.YZero;
        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        //long preTime = 0;
        private const long MIN_TIME= 15000;
        private void DrawingCanvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {

            double positionX = e.GetPosition(this).X;
            if (mMode == MouseMode.VIEW)
            {
                int len = drawingCanvas.AllDatas[0].EndIndex - drawingCanvas.AllDatas[0].StartIndex+1;
                if (positionX > x0 && positionX < x0+mWidth && Math.Abs(positionX - preMoved) >= mWidth / len)
                {
                    //计算速度鼠标移动速度,如果速度过快 ,则不绘制
                    if (stopwatch.IsRunning)
                    {
                        stopwatch.Stop();
                    }
                    long curTime = stopwatch.ElapsedTicks;
                    //Console.WriteLine(curTime);
                    if(curTime > MIN_TIME)
                    {
                        this.PolyText(positionX);
                    }
                    stopwatch.Restart();
                    preMoved = positionX;

                }
            }
            else if (isMouseDown && startDown > x0 && startDown < mWidth+x0)
            {
                isMouseMoved = true;
                this.PolyRect(startDown, positionX);
            }

            //stopwatch.Start();
        }

        private bool isMouseDown = false;
        private bool isMouseMoved = false;
        private double startDown;
        private double endup;
        private int clickTimes = 0;
        private void DrawingCanvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {

            isMouseDown = true;
            mMode = MouseMode.ZOOM;
            startDown = e.GetPosition(this).X;
            this.RemoveVisual(textVisual);
            this.InvalidateVisual();
            //双击
            clickTimes++;
            DispatcherTimer timer = new DispatcherTimer();

            timer.Interval = new TimeSpan(0, 0, 0, 0, 300);

            timer.Tick += (s, e1) => { timer.IsEnabled = false; clickTimes = 0; };

            timer.IsEnabled = true;

            if (clickTimes % 2 == 0)
            {
                //Console.WriteLine("double");
                timer.IsEnabled = false;

                clickTimes = 0;
                foreach (LineDatas data in drawingCanvas.AllDatas)
                {
                    data.StartIndex = 0;
                    data.EndIndex = data.RtData.Count - 1;
                }

                drawingCanvas.Polyline();
                drawingCanvas.InvalidateVisual();
                //this.InvalidateVisual();
            }
        }

        //获取Visual的个数
        protected override int VisualChildrenCount
        {
            get { return visuals.Count; }
        }

        public double MWidth
        {
            get
            {
                return mWidth;
            }

            set
            {
                mWidth = value;
            }
        }

        public double MHeight
        {
            get
            {
                return mHeight;
            }

            set
            {
                mHeight = value;
            }
        }

        public double CanvasWidth
        {
            get
            {
                return canvasWidth;
            }

            set
            {
                canvasWidth = value;
                this.Width = value;
                mWidth = value - x0 - y0;
            }
        }

        //获取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);
            //visual = null;
        }

        //命中测试
        public DrawingVisual GetVisual(Point point)
        {
            HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
            return hitResult.VisualHit as DrawingVisual;
        }

        //绘制鼠标选择放大的矩形
        DrawingVisual rectVisual;
        public void PolyRect(double startx, double endx)
        {
            if (rectVisual != null)
            {
                this.RemoveVisual(rectVisual);
            }
            rectVisual = new DrawingVisual();
            DrawingContext dc = rectVisual.RenderOpen();

            Pen pen = new Pen(new SolidColorBrush(Color.FromArgb(100, 255, 200, 200)), 1);
            dc.DrawRectangle(new SolidColorBrush(Color.FromArgb(100, 255, 200, 200)), pen, new Rect(new Point(startx, y0), new Point(endx, y0+mHeight)));
            dc.Close();
            this.AddVisual(rectVisual);
            this.InvalidateVisual();
        }
        //绘制显示选中的数值
        DrawingVisual textVisual;
        public void PolyText(double xPosition)
        {
            if (drawingCanvas.AllDatas.Count < 1)
                return;
            if (textVisual != null)
            {
                this.RemoveVisual(textVisual);
            }
            textVisual = new DrawingVisual();

            DrawingContext dc = textVisual.RenderOpen();
            int len = drawingCanvas.AllDatas[0].EndIndex - drawingCanvas.AllDatas[0].StartIndex+1;
            double step = mWidth / len;
           // Console.WriteLine("*****linestep:" + step);
            int index = (int)((xPosition - x0) / step);
            double ax = x0 + index * step;
            //竖线
            Pen pen = new Pen(Brushes.Transparent, 3);
            pen.Freeze();
            FormattedText[] ftXs = new FormattedText[drawingCanvas.AllDatas.Count];

            for (int i = 0; i < drawingCanvas.AllDatas.Count; i++)
            {
                int mIndex = index + drawingCanvas.AllDatas[i].StartIndex;
                ftXs[i] = new FormattedText("X:" + drawingCanvas.AllDatas[i].XData[mIndex] + " 实测:" + drawingCanvas.AllDatas[i].RtData[mIndex] + " 设计:" + drawingCanvas.AllDatas[i].ThData[mIndex], new System.Globalization.CultureInfo("zh-CHS", false), FlowDirection.LeftToRight, new Typeface("Microsoft YaHei"), 15, Brushes.White);
                //计算是否超出范围
                if (ax + ftXs[i].Width < x0+mWidth)
                {
                    dc.DrawRectangle(new SolidColorBrush(Color.FromArgb(200, 0, 150, 179)), pen, new Rect(new Point(ax, (i+1)*y0+i*drawingCanvas.YHeight), new Point(ax + ftXs[i].Width, (i + 1) * y0 + i * drawingCanvas.YHeight + ftXs[i].Height)));
                    dc.DrawText(ftXs[i], new Point(ax, (i + 1) * y0 + i * drawingCanvas.YHeight));
                }
                else
                {
                    dc.DrawRectangle(new SolidColorBrush(Color.FromArgb(200, 0, 150, 179)), pen, new Rect(new Point(ax - ftXs[i].Width, (i + 1) * y0 + i * drawingCanvas.YHeight), new Point(ax, (i + 1) * y0 + i * drawingCanvas.YHeight + ftXs[i].Height)));
                    dc.DrawText(ftXs[i], new Point(ax - ftXs[i].Width, (i + 1) * y0 + i * drawingCanvas.YHeight));
                }
            }
            Pen penLine = new Pen(new SolidColorBrush(Color.FromArgb(200, 0, 150, 179)), 3);
            penLine.DashStyle = new DashStyle(new double[] { 2.5, 2.5 }, 0);
            penLine.Freeze();
            dc.DrawLine(penLine, new Point(ax,y0), new Point(ax, y0+mHeight));
            dc.Close();
            this.AddVisual(textVisual);
            this.InvalidateVisual();
        }

    }
}

上面两段代码中,我把需要绘制的数据属性单独抽象出来

LineDatas.CS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;

namespace Zero_Gjy.UserControls
{
    class LineDatas
    {
        string title;
        double min;
        double max;
        DoubleCollection xData;
        DoubleCollection rtData;
        DoubleCollection thData;
        int startIndex;
        int endIndex;
        public double Min
        {
            get
            {
                return min;
            }

            set
            {
                min = value;
            }
        }

        public double Max
        {
            get
            {
                return max;
            }

            set
            {
                max = value;
            }
        }

        public string Title
        {
            get
            {
                return title;
            }

            set
            {
                title = value;
            }
        }

        public DoubleCollection RtData
        {
            get
            {
                return rtData;
            }

            set
            {
                rtData = value;
                min = value.Min();
                max = value.Max();
            }
        }

        public DoubleCollection ThData
        {
            get
            {
                return thData;
            }

            set
            {
                thData = value;

            }
        }

        public int StartIndex
        {
            get
            {
                return startIndex;
            }

            set
            {
                startIndex = value;
            }
        }

        public int EndIndex
        {
            get
            {
                return endIndex;
            }

            set
            {
                endIndex = value;
            }
        }

        public DoubleCollection XData
        {
            get
            {
                return xData;
            }

            set
            {
                xData = value;
            }
        }

        public LineDatas()
        {
            this.title = "";
            this.Max = 0;
            this.Min = 0;
            this.XData = new DoubleCollection();
            this.RtData = new DoubleCollection();
            this.ThData = new DoubleCollection();

        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="_title">数据标题</param>
        /// <param name="min">数据最小值</param>
        /// <param name="max">数据最大值</param>
        /// <param name="_xData">x坐标</param>
        /// <param name="rtdata">实测数据</param>
        /// <param name="thdata">理论数据</param>
        public LineDatas(string _title,double min, double max, DoubleCollection _xData, DoubleCollection rtdata,DoubleCollection thdata)
        {
            this.title = _title;
            this.Min = min;
            this.Max = max;
            this.XData = _xData;
            this.RtData = rtdata ;
            this.ThData = thdata;
            this.StartIndex = 0;
            this.EndIndex = rtData.Count - 1;
        }
        public void clear()
        {
            this.XData.Clear();
            this.RtData.Clear();
            this.ThData.Clear();
        }
    }
}

经过这样的改进,鼠标在界面移动时显示数据明显顺畅了很多。



WPF 自定义的图表(适用大量数据绘制)下的更多相关文章

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

    原文:WPF 自定义的图表(适用大量数据绘制) 在WPF中绘制图表比较简单,有很多的第三方控件,但是在绘制大量数据的时候,就显得有些吃力,即便是自己用StreamGeometry画也达不到理想的效果, ...

  2. Highcharts使用CSV格式数据绘制图表

    Highcharts使用CSV格式数据绘制图表 CSV(Comma-Separated Values,逗号分隔值文本格式)是採用逗号切割的纯文本数据.通常情况下.每一个数据之间使用逗号切割,几个相关数 ...

  3. linux环境安装nagiosgraph将nagios的性能数据绘制成动态图表?

    需求描述: 在安装完成nagios之后,比如有监控磁盘负载信息的,连接数的,进程数的,可以通过安装nagiosgraph软件, 将nagios的性能数据绘制成图表,可以看到一段时间内数据的变化 环境说 ...

  4. Highcharts使用表格数据绘制图表

    Highcharts使用表格数据绘制图表 在Highcharts中,同意用户使用网页中现有的表格数据作为数据来源,然后依据该数据来源绘制图表.对于一个典型的HTML表格.当中,第一列的数据会作为x轴刻 ...

  5. DevExpress WPF v19.2图表图形控件功能增强?速速种草

    通过DevExpress WPF Controls,你能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案. 无论是Office办公软件的衍 ...

  6. WPF 自定义柱状图 BarChart

    WPF 自定义柱状图 当前的Telerik控件.DevExpress控件在图表控件方面做得不错,但是有时项目中需要特定的样式,不是只通过修改图表的模板和样式就能实现的. 或者说,通过修改当前的第三方控 ...

  7. WPF 自定义雷达图

    自定义雷达图表如下: Git下载地址:https://github.com/Kybs0/RadarChartControl 1.创建UserControl,名为“RadarChartControl” ...

  8. WPF自定义LED风格数字显示控件

    原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/article/de ...

  9. wpf 自定义圆形按钮

    wpf 自定义圆形按钮 效果图 默认样式 获取焦点样式 点击样式 下面是实现代码: 一个是自定义控件类,一个是控件类皮肤 using System; using System.Collections. ...

随机推荐

  1. 哈夫曼(huffman)树和哈夫曼编码

    哈夫曼树 哈夫曼树也叫最优二叉树(哈夫曼树) 问题:什么是哈夫曼树? 例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80-89分: B,70-79分: C,60-69分: D,<60 ...

  2. Css 相关资源(本篇不定期更新)

    http://www.tuicool.com/articles/3eaINn---<终于搞懂了CSS实现三角形图标的原理>---☆☆☆☆☆.这篇讲的是css中的如何挤出一个三角形,这个讲的 ...

  3. Java for LeetCode 189 Rotate Array

    Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array ...

  4. 感知机学习算法 python实现

    参考李航<统计学习方法> 一开始的感知机章节,看着不太复杂就实现一下... """ 感知机学习算法的原始形式 例2.1 """ ...

  5. cocos2d-x——在一个cpp中展示多个场景

    //20秒后自动运行下一个场景 runAction( CCSequence::create(CCDelayTime::create(20.0f), CCCallFunc::create(this, c ...

  6. (转载)与OpenDialog相关的一个问题

    OpenDialog的一个问题 有一个功能要求就是[每次打开文件的对话框的默认路径是上一次保存文件的路径],本来这个就是设置OpenDialog控件的InitialDir属性就行了,但是第一次打开的时 ...

  7. hdu 1251(字典树)

    题目链接:http://acm.hdu.edu.cn/status.php?user=NYNU_WMH&pid=1251&status=5 Trie树的基本实现 字母树的插入(Inse ...

  8. 主题模型 利用gibbslda做数据集主题抽样

    电子科技大学电子商务实验室Kai Yip,欢迎同行指正,也欢迎互相指导,学习. 广告打完,进入正题. 关于程序运行结果的分析请参照我的另一篇博客:http://www.cnblogs.com/nlp- ...

  9. 关于sqlserver还原不了数据库的原因

    因为备份文件需要在服务器上打成压缩包,才能进行传输,不然会丢失数据..

  10. 201521123076 《Java程序设计》 第十四周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...