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的操作
??????????? //初始化paneChartCompareHelper.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;#endregiontreeList.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//用來存儲標題不為空的listList<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;//曲線總數小于100if (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);}#endregionSymbolType 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了 則賦值為100progressBar.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);} ..?
總結
以上是生活随笔為你收集整理的Winform中实现双击Dev的TreeList在ZedGraph中生成对应颜色的曲线的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Winform中设置ZedGraph在生
- 下一篇: C#中导出百万级Excel只需几秒除了N