Winform中实现双击Dev的TreeList在ZedGraph中生成对应颜色的曲线

场景

首先要实现的效果如下

在实现上面的效果前参照下面的博客

DevExpress的TreeList怎样设置数据源使其显示成单列树形结构:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/102742426

DevExpress的TreeList怎样设置数据源,从实例入手:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/102548490

Winform中设置ZedGraph在生成多条曲线时随机采用不同的颜色:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/106663474

注:

博客主页:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

首先 新建页面并设计页面布局如下,左边两个TreeList,右边是一个ZedGraph

然后在此页面的load事件中进行初始化ZedGraph的操作

           //初始化pane
            ChartCompareHelper.InitGraphPane(this.zedGraphControl1,true);

在方法InitGraphPane中根据自己需要进行一些属性的设置。

            #region 曲线图控件属性设置

            zgc.IsEnableZoom = true;                        //允许缩放
            zgc.IsShowContextMenu = true;                   //显示上下文菜单
            zgc.IsShowCopyMessage = false;                   //复制图像时显示提示信息
            zgc.IsZoomOnMouseCenter = true;                 //缩放以鼠标为中心
            zgc.IsShowPointValues = true;                   //是否显示线上的点
            //zgc.IsShowCursorValues = true;                  //显示坐标- 如果使用则画出的十字线中Y没法取值
            zgc.ZoomStepFraction = 0.05;                    //调整缩放时的鼠标灵敏度 数值越大越灵敏
            zgc.GraphPane.Border.IsVisible = true;

            #endregion

            #region 初始化图形面板及坐标轴

            GraphPane myPane = zgc.GraphPane;

            SetGraphPanelStyle(myPane);
            //图例不显示
            myPane.Legend.IsVisible = false;

            myPane.XAxis.Type = AxisType.Linear;                //初始X轴按值显示

            myPane.YAxis.Title.IsVisible = true;
           
            myPane.YAxis.MajorGrid.IsVisible = true;            //显示主刻度网格线

            #endregion

同样在上面的load方法中还要进行初始化两个treelist的操作

ChartCompareHelper.RefreshCycleTreeData(this.treeList1, this.defaultExpandLevel);
         
ChartCompareHelper.SetComTreeListStyle(this.treeList2);

第一个方法是进行上面第一个数的设置数据源

        public static void RefreshCycleTreeData(DevExpress.XtraTreeList.TreeList treeList, int expandToLevel)
        {
           
            //设置曲线对比中待比较的数据源
            string fieldName = "NodeText";
            string keyFieldName = "Id";
            string parentFieldName = "ParentId";
            
            IEnumerable<IGrouping<int, Record>> groups = Global.Instance.VirtualData.RecordDataList.GroupBy(p => p.CycleIndex);
            Global.Instance.CompareDataInOne.Clear();
            foreach(var group in groups)
            {

                DataTreeNode node = new DataTreeNode();
                node.ParentId = null;
                node.NodeText = "循环" + group.Key;
                node.NodeType = DataTreeNodeTypes.File;
                node.Id = group.Key.ToString();
                Global.Instance.CompareDataInOne.Add(node);
            }
           
            DataTreeListHelper.SetComInOneTreeListDataSource(treeList, Global.Instance.CompareDataInOne, fieldName, keyFieldName, parentFieldName,1);
            treeList.RefreshDataSource();
            treeList.ExpandToLevel(expandToLevel);
        }

在此方法中上面是构造出数据源的操作,具体可以参照上面的博客。

然后调用了SetComInOneTreeListDataSource方法,为了区分传递的这两个treelist,参数中设置了flag变量。

public static void SetComInOneTreeListDataSource(DevExpress.XtraTreeList.TreeList treeList, List<DataTreeNode> data, string fieldName, string keyFieldName, string parentFieldName,int treeFlag)
        {
            #region 设置节点图标

 

            //数据节点双击选中
            treeList.MouseDoubleClick -= treeList_MouseDoubleClick_InOne;
            treeList.MouseDoubleClick += treeList_MouseDoubleClick_InOne;

            if(treeFlag ==2)
            {
                //重新绘制节点颜色事件
                treeList.CustomDrawNodeCell -= treeList_CustomDrawNodeCellInOne;
                treeList.CustomDrawNodeCell += treeList_CustomDrawNodeCellInOne;
            }


            #endregion

            #region 设置列头、节点指示器面板、表格线样式

            treeList.OptionsView.ShowColumns = false;             //隐藏列标头
            treeList.OptionsView.ShowIndicator = false;           //隐藏节点指示器面板

            treeList.OptionsView.ShowHorzLines = false;           //隐藏水平表格线
            treeList.OptionsView.ShowVertLines = false;           //隐藏垂直表格线
            treeList.OptionsView.ShowIndentAsRowStyle = false;

            #endregion

            treeList.LookAndFeel.UseDefaultLookAndFeel = false;       //禁用默认外观与感觉
            treeList.LookAndFeel.UseWindowsXPTheme = true;            //使用WindowsXP主题
            treeList.TreeLineStyle = DevExpress.XtraTreeList.LineStyle.Percent50;     //设置树线的样式

            #region 添加单列

            DevExpress.XtraTreeList.Columns.TreeListColumn colNode = new DevExpress.XtraTreeList.Columns.TreeListColumn();
            colNode.Name = String.Format("col{0}", fieldName);
            colNode.Caption = fieldName;
            colNode.FieldName = fieldName;
            colNode.VisibleIndex = 0;
            colNode.Visible = true;

            colNode.OptionsColumn.AllowEdit = false;                        //是否允许编辑
            colNode.OptionsColumn.AllowMove = false;                        //是否允许移动
            colNode.OptionsColumn.AllowMoveToCustomizationForm = false;     //是否允许移动至自定义窗体
            colNode.OptionsColumn.AllowSort = false;                        //是否允许排序
            colNode.OptionsColumn.FixedWidth = false;                       //是否固定列宽
            colNode.OptionsColumn.ReadOnly = true;                          //是否只读
            colNode.OptionsColumn.ShowInCustomizationForm = true;           //移除列后是否允许在自定义窗体中显示

            treeList.Columns.Clear();
            treeList.Columns.AddRange(new DevExpress.XtraTreeList.Columns.TreeListColumn[] { colNode });
            #endregion

            #region 绑定数据源

            treeList.DataSource = null;
            treeList.KeyFieldName = keyFieldName;
            treeList.ParentFieldName = parentFieldName;
            treeList.DataSource = data;
            treeList.RefreshDataSource();

            #endregion


        }

在这方法中设置了节点的双击事件treeList_MouseDoubleClick_InOne;和对下面的treelist重新进行绘制节点的事件。

在treeList_MouseDoubleClick_InOne;中

       private static void treeList_MouseDoubleClick_InOne(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                DevExpress.XtraTreeList.TreeList treeList = sender as DevExpress.XtraTreeList.TreeList;
                if (treeList != null && treeList.Selection.Count == 1)
                {
                    object idValue = null;
                    string strIdValue = String.Empty;
                    DataTreeNode nodeData = null;
                    List<DataTreeNode> datasource = treeList.DataSource as List<DataTreeNode>;
                    if (datasource != null)
                    {
                        idValue = treeList.Selection[0].GetValue("Id");
                        strIdValue = idValue.ToString();
                        nodeData = datasource.Where<DataTreeNode>(p => p.Id == strIdValue).FirstOrDefault<DataTreeNode>();
                        if (nodeData != null)
                        {
                            if (nodeData.NodeType == DataTreeNodeTypes.File)
                            {
                                ParamEventArgs pea = new ParamEventArgs(nodeData.Id);
                                TriggerReloadSelectDataEventInOne(sender, pea);
                                return;
                            }
                        }
                    }
                }
            }
        }

主要就是获取当前节点的id并触发刷新事件TriggerReloadSelectDataEventInOne

        public static void TriggerReloadSelectDataEventInOne(object sender, System.EventArgs e)
        {
            if (OnReloadSelectDataInOne != null)
            {
                OnReloadSelectDataInOne(sender, e);
            }
        }

而OnReloadSelectDataInOne是自定义的

public static event EventHandler OnReloadSelectDataInOne;

然后在最上面的页面的代码中进行订阅

DataTreeListHelper.OnReloadSelectDataInOne -= DataTreeListHelper_OnReloadSelectDataInOne;
DataTreeListHelper.OnReloadSelectDataInOne += DataTreeListHelper_OnReloadSelectDataInOne;

在订阅事件中进行刷新下面treelist和右边ZedGraph的操作。继续上面SetComInOneTreeListDataSource中设置了第二个treelist的自定义事件treeList_CustomDrawNodeCellInOne

  

      private static void treeList_CustomDrawNodeCellInOne(object sender, DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs e)
        {
            //确定列的名字不为空
            if (e.Column.Name.ToString() != null)
            {
                if (Global.Instance.CurveComColorMappingInOne.ContainsKey(e.CellValue.ToString()))
                {
                    Color color = new Color();
                    Global.Instance.CurveComColorMappingInOne.TryGetValue(e.CellValue.ToString(), out color);
                    //设置背景色
                    e.Appearance.BackColor = color;
                    //设置开启背景色
                    e.Appearance.Options.UseBackColor = true;
                    //设置前景色
                    e.Appearance.ForeColor = Color.White;
                    //设置开启前景色
                    e.Appearance.Options.UseForeColor = true;
                }
            }
        }

这里的逻辑是在双击第一个treelist的加载事件DataTreeListHelper_OnReloadSelectDataInOne中刷新ZedGraph时生成曲线时将节点与颜色的对应关系存储在全局的映射关系Global.Instance.CurveComColorMappingInOne中,其定义为

 private Dictionary<string, System.Drawing.Color> _curveComColorMappingInOne = new Dictionary<string, System.Drawing.Color>();  

        public Dictionary<string, System.Drawing.Color> CurveComColorMappingInOne
        {
            get { return _curveComColorMappingInOne; }
            set { _curveComColorMappingInOne = value; }
        }

继续上面设置第二个treelist的方法SetComTreeListStyle

       public static void SetComTreeListStyle(DevExpress.XtraTreeList.TreeList treeList)
        {
            #region 设置节点图标

            System.Windows.Forms.ImageList imgList = new System.Windows.Forms.ImageList();
            imgList.Images.AddRange(imgs);

            treeList.SelectImageList = imgList;

           
            #endregion

            #region 设置列头、节点指示器面板、表格线样式

            treeList.OptionsView.ShowColumns = false;             //隐藏列标头
            treeList.OptionsView.ShowIndicator = false;           //隐藏节点指示器面板

            treeList.OptionsView.ShowHorzLines = false;           //隐藏水平表格线
            treeList.OptionsView.ShowVertLines = false;           //隐藏垂直表格线
            treeList.OptionsView.ShowIndentAsRowStyle = false;

            #endregion

            #region 初始禁用单元格选中,禁用整行选中

            treeList.OptionsView.ShowFocusedFrame = true;                               //设置显示焦点框
            treeList.OptionsSelection.EnableAppearanceFocusedCell = false;              //禁用单元格选中
            treeList.OptionsSelection.EnableAppearanceFocusedRow = false;               //禁用正行选中
          

            #endregion

            #region 设置TreeList的展开折叠按钮样式和树线样式

            treeList.OptionsView.ShowButtons = true;                  //显示展开折叠按钮
            treeList.LookAndFeel.UseDefaultLookAndFeel = false;       //禁用默认外观与感觉
            treeList.LookAndFeel.UseWindowsXPTheme = true;            //使用WindowsXP主题
            treeList.TreeLineStyle = DevExpress.XtraTreeList.LineStyle.Percent50;     //设置树线的样式

            #endregion

            #region 添加单列
            DevExpress.XtraTreeList.Columns.TreeListColumn colNode = new DevExpress.XtraTreeList.Columns.TreeListColumn();
            colNode.VisibleIndex = 0;
            colNode.Visible = true;
            colNode.OptionsColumn.AllowEdit = false;                        //是否允许编辑
            colNode.OptionsColumn.AllowMove = false;                        //是否允许移动
            colNode.OptionsColumn.AllowMoveToCustomizationForm = false;     //是否允许移动至自定义窗体
            colNode.OptionsColumn.AllowSort = false;                        //是否允许排序
            colNode.OptionsColumn.FixedWidth = false;                       //是否固定列宽
            colNode.OptionsColumn.ReadOnly = true;                          //是否只读
            colNode.OptionsColumn.ShowInCustomizationForm = true;           //移除列后是否允许在自定义窗体中显示
            treeList.Columns.Clear();
            treeList.Columns.AddRange(new DevExpress.XtraTreeList.Columns.TreeListColumn[] { colNode });

            #endregion

        }

然后在双击第一个treelist的节点的触发并订阅事件DataTreeListHelper_OnReloadSelectDataInOne中进行刷新第二个treeList和ZedGraph的操作,这里只有关键代码

  

          #region 设置曲线对比待比较面板的数据源-同文件

            //设置曲线对比中待比较的数据源
            string fieldName = "NodeText";
            string keyFieldName = "Id";
            string parentFieldName = "ParentId";
            DataTreeNode node = new DataTreeNode();
            node.ParentId = null;
            node.NodeText = "循环" + currentNode.Id;
            node.NodeType = DataTreeNodeTypes.File;
            node.Id = currentNode.Id;
            //加入待比较列表
            Global.Instance.PrepareCompareDataInOne.Add(currentNode);
            DataTreeListHelper.SetComInOneTreeListDataSource(this.treeList2, Global.Instance.PrepareCompareDataInOne, fieldName, keyFieldName, parentFieldName,2);
            this.treeList2.RefreshDataSource();

            #endregion

            #region 刷新图形显示
            List<YAxisModel> yAxisModelList = new List<YAxisModel>();
            yAxisModelList = ChartOptionHelper.GetYAxisList(System.IO.Path.Combine(Global.AppConfig.SysConfigPath, Global.RADIO_GROUP_YAXIS_FILEPATH_RECORD_CURVE_COMPARE_INONE));
            ChartCompareHelper.RefreshPaneComInOne(this.zedGraphControl1, yAxisModelList,this.progressBarControl1);

            #endregion

主要是在刷新ZedGraph的方法RefreshPaneComInOne中

public static void RefreshPaneComInOne(ZedGraphControl zgc, List<YAxisModel> yLoadList,ProgressBarControl progressBar)
        {
            #region 清空图形中的对象

            zgc.GraphPane.GraphObjList.Clear();

            #endregion

            #region 获取panel对象

            GraphPane myPane = zgc.GraphPane;

            //设置标题
            string title = System.IO.Path.GetFileNameWithoutExtension(Global.Instance.CurrDataFile);
            string parent = System.IO.Directory.GetParent(Global.Instance.CurrDataFile).ToString();
            parent = parent.Substring(parent.LastIndexOf('\') + 1);

            myPane.Title.Text = parent +"-"+title;

            myPane = SetGraphPanelStyle(myPane);                              //Pane公共属性设置

            #endregion

            #region 设置X轴属性

            XAxisModel xAxisModel = new XAxisModel();
            xAxisModel.Title = "相对时间";
            xAxisModel.Color = "black";
            SetXAxisStyle(myPane.XAxis, xAxisModel);        //X轴公共属性设置


            #endregion

            #region 筛选Y轴list

            //用来存储标题不为空的list
            List<YAxisModel> yList = new List<YAxisModel>();
            foreach (YAxisModel yAxisModel in yLoadList)
            {
                if (!yAxisModel.Title.Equals(""))
                {
                    yList.Add(yAxisModel);
                }
            }
            #endregion

            #region 没有选择曲线的情况下,默认显示一个Y轴

            if (yList == null || yList.Count == 0)
            {
                myPane.XAxis.Title.Text = "X";               //设置X轴标题
                myPane.XAxis.Color = Color.Black;                   //X轴线的颜色

                //设置第一条Y轴标题
                myPane.YAxisList.Clear();
                YAxis yAxisNew = new YAxis("Y");
                myPane.YAxisList.Add(yAxisNew);
            }

            #endregion

            #region 当选择一条或多条曲线,则根据选择曲线的数量显示Y轴数量

            if (yList != null && yList.Count > 0)
            {
                myPane.YAxisList.Clear();                           //清除原有Y轴坐标
                for (int i = 0; i < yList.Count; i++)
                {
                    YAxis yAxisNew = new YAxis(yList[i].Title);
                   
                    if (i == 0)
                    {
                        yAxisNew.MajorGrid.IsVisible = true;           //显示第一个Y轴的主刻度网格线
                    }                 
                    SetNewYAxisStyleInCycleCom(myPane, yAxisNew, yList[i]);
                }
                
            }

            #endregion

            #region  关掉十次幂显示
            myPane.YAxisList.ForEach(p => p.Scale.MagAuto = false);
            #endregion

            #region 截取前100个循环进行显示

          
            if (Global.Instance.PrepareCompareDataInOne.Count > 100)
            {
                Global.Instance.PrepareCompareDataInOne.RemoveRange(100, Global.Instance.PrepareCompareDataInOne.Count - 100);
            }

            #endregion

            #region 获取记录数最多的节点号

            //获取记录数最多的节点号
            int maxCountNum = 0;
            int maxCountNode = 0;
            foreach(DataTreeNode node in Global.Instance.PrepareCompareDataInOne)
            {
                IEnumerable<IGrouping<int, Entity.Record>> groups = Global.Instance.VirtualData.RecordDataList.GroupBy(p => p.CycleIndex);
                int count = Global.Instance.VirtualData.RecordDataList.Where(p => p.CycleIndex == int.Parse(node.Id)).Count();
                if (count > maxCountNum)
                {
                    maxCountNum = count;
                    maxCountNode = int.Parse(node.Id);
                }
            }

            #endregion

            #region 获取记录最多的循环

            List<Entity.Record> maxCountList = new List<Entity.Record>();
            //获取记录最多的循环
            IEnumerable<Entity.Record> maxCycle = Global.Instance.VirtualData.RecordDataList.Where(p => p.CycleIndex == maxCountNode);
            Entity.Record  firstRecord = maxCycle.FirstOrDefault();
            foreach(Entity.Record record in maxCycle)
            {
                //减去第一个记录的测试时间
                record.TestTime = record.TestTime - firstRecord.TestTime;
                
                //保留4位小数
                //record.TestTime = Math.Round(record.TestTime, 4);
            }

            #endregion

            #region 颜色数组
            //用于存取取出的颜色对象
            List<Color> colorList = new List<Color>(){ 
                        Color.Blue,
                        Color.Red,
                        Color.Green,
                        Color.Magenta,
                        Color.MediumBlue,
                        Color.BlueViolet,
                        Color.Maroon,
                        Color.Chartreuse,
                        Color.Aqua,
                        Color.Indigo,
                        Color.Aquamarine,
                        Color.OrangeRed,
                        Color.Sienna,
                        Color.SeaGreen,
                        Color.Black,
                        Color.OliveDrab,
                        Color.Purple,
                        Color.Brown,
                        Color.Navy,
                        Color.BurlyWood,
                        Color.MediumSpringGreen,
                        Color.Chocolate,
                        Color.Salmon,
                        Color.SaddleBrown,
                        Color.RoyalBlue,
                        Color.Coral,
                        Color.Crimson,
                        Color.Tomato,
                        Color.Cyan,
                        Color.Lime,
                        Color.MediumVioletRed,
                        Color.MidnightBlue,
                        Color.Olive,
                        Color.Orange,
                        Color.SaddleBrown,
                        Color.HotPink,
                    };

            //转成数组
            Color[] colors = colorList.OrderBy(p => Guid.NewGuid().ToString()).ToArray();       //把集合随机排序后转为数组

            #endregion

            #region  更新曲线数据

            myPane.CurveList.Clear();                           //清除原有曲线
            
            if (yList != null && yList.Count > 0)
            {
              

                PointPairList list = null;
                int curveIndex = 0;
                for (int i = 0; i < yList.Count; i++)
                {
                    //截取前100个循环进行显示
                    //Global.Instance.PrepareCompareDataInOne = Global.Instance.PrepareCompareDataInOne.Where(p => (int.Parse(p.Id) < 101)).ToList();
                    //计算进度条步长
                    int step = 1;
                    //曲线总数小于100 
                    if (Global.Instance.PrepareCompareDataInOne.Count < 100)
                    {
                        step = 100 / Global.Instance.PrepareCompareDataInOne.Count;
                    }
                    else
                    {
                        step = Global.Instance.PrepareCompareDataInOne.Count / 100;
                    }
                    if(progressBar !=null)
                    {
                        //将进度条初始化为0%
                        progressBar.Position = 0;
                    }
                   
                    int index = 0;
                    //循环添加曲线
                    foreach(DataTreeNode node in Global.Instance.PrepareCompareDataInOne)
                    {
                        IEnumerable<Entity.Record> record =  Global.Instance.VirtualData.RecordDataList.Where(p => p.CycleIndex == int.Parse(node.Id));
                        list = SetCurveTextInOne(yList[i].TitleKey,record);


                       
                        #region  根据节点值获取映射的颜色
                        //  取得颜色
                        Color curveColor = new Color();
                        //节点名称
                        string nodeName = "循环" + node.Id;
                        //将颜色的映射关系存储
                        //已经有了 则直接取用
                        if (Global.Instance.CurveComColorMappingInOne.ContainsKey(nodeName))
                        {
                            Global.Instance.CurveComColorMappingInOne.TryGetValue(nodeName, out curveColor);

                        }
                        //没有则新增并存储
                        else
                        {
                            curveColor = colors[curveIndex % colors.Length];
                            Global.Instance.CurveComColorMappingInOne.Add(nodeName, curveColor);
                        }

                        #endregion
                        SymbolType symbolType = GetCurveSimple(yList[i].CurveType);  
                        LineItem myCurve = myPane.AddCurve(yList[i].Title, list, curveColor, symbolType);
                        myCurve = SetCurveType(myCurve, symbolType, yList[i].Type, curveColor);
                        index++;
                        //使用Tag存储循环号
                        myCurve.Tag = node.Id;
                        myCurve.YAxisIndex = i;                                                                 //很关键,对应使用那个坐标值
                        if(progressBar !=null)
                        {
                            //添加成功一条曲线则进度条增加一个步数
                            progressBar.Position += step;
                            if (progressBar.Position >=100)
                            {
                                //如果总进度已经大于100了 则赋值为100
                                progressBar.Position = 100;
                            }
                            //更新进度条的进度
                            progressBar.Update();
                        }

                        curveIndex++;
                    }
                    if (progressBar != null)
                    {
                        //最终添加完所有曲线后将进度条设置为100%
                        progressBar.Position = 100;
                    }
                }
                if (list!= null)
                {
                    string[] labels = new string[maxCycle.Count()];
                    int index = 0;
                    foreach( Entity.Record record in maxCycle)
                    {
                        labels[index] = DataProcessor.FormatFloatToDateTimeString(record.TestTime);
                        index ++;
                    }
                    //myPane.XAxis.Scale.TextLabels = list.Select<PointPair, string>(p => p.X.ToString()).ToArray<string>();         //X轴文本取值
                    //myPane.XAxis.Scale.TextLabels = maxCycle.Select(p => p.TestTime.ToString()).ToArray<string>();         //X轴文本取值
                    myPane.XAxis.Scale.TextLabels = labels;         //X轴文本取值
                }
            }
    
            #endregion

            #region 使数据变化生效

            zgc.AxisChange();
            zgc.Invalidate();
            zgc.Refresh();

            #endregion
        }

大部分与业务相关的代码,只要在生成曲线并添加节点与颜色映射的代码

           #region 颜色数组
            //用于存取取出的颜色对象
            List<Color> colorList = new List<Color>(){ 
                        Color.Blue,
                        Color.Red,
                        Color.Green,
                        Color.Magenta,
                        Color.MediumBlue,
                        Color.BlueViolet,
                        Color.Maroon,
                        Color.Chartreuse,
                        Color.Aqua,
                        Color.Indigo,
                        Color.Aquamarine,
                        Color.OrangeRed,
                        Color.Sienna,
                        Color.SeaGreen,
                        Color.Black,
                        Color.OliveDrab,
                        Color.Purple,
                        Color.Brown,
                        Color.Navy,
                        Color.BurlyWood,
                        Color.MediumSpringGreen,
                        Color.Chocolate,
                        Color.Salmon,
                        Color.SaddleBrown,
                        Color.RoyalBlue,
                        Color.Coral,
                        Color.Crimson,
                        Color.Tomato,
                        Color.Cyan,
                        Color.Lime,
                        Color.MediumVioletRed,
                        Color.MidnightBlue,
                        Color.Olive,
                        Color.Orange,
                        Color.SaddleBrown,
                        Color.HotPink,
                    };

            //转成数组
            Color[] colors = colorList.OrderBy(p => Guid.NewGuid().ToString()).ToArray();       //把集合随机排序后转为数组
....

                    //循环添加曲线
                    foreach(DataTreeNode node in Global.Instance.PrepareCompareDataInOne)
                    {
                        IEnumerable<Entity.Record> record =  Global.Instance.VirtualData.RecordDataList.Where(p => p.CycleIndex == int.Parse(node.Id));
                        list = SetCurveTextInOne(yList[i].TitleKey,record);


                       
                        #region  根据节点值获取映射的颜色
                        //  取得颜色
                        Color curveColor = new Color();
                        //节点名称
                        string nodeName = "循环" + node.Id;
                        //将颜色的映射关系存储
                        //已经有了 则直接取用
                        if (Global.Instance.CurveComColorMappingInOne.ContainsKey(nodeName))
                        {
                            Global.Instance.CurveComColorMappingInOne.TryGetValue(nodeName, out curveColor);

                        }
                        //没有则新增并存储
                        else
                        {
                            curveColor = colors[curveIndex % colors.Length];
                            Global.Instance.CurveComColorMappingInOne.Add(nodeName, curveColor);
                        }
..
原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/13091343.html