最近在研究WPF,需要用到類似Chart的控件來繪制折線圖,橫坐標自定義時間信息。先后研究了DynamicDataDisplay.ChartPlotter、Toolkit,因為WPF用的人太少了,這方面可以查到的資料太少了。DynamicDataDisplay.ChartPlotter雖然能實現橫坐標顯示時間,但是我想顯示的是歷史的時間信息,非當下時間,遂棄之。如果有知道的大神,可以提點下我怎么改。
以上種種,導致我想用熟悉的Winform下的Chart來繪制。
1.首先添加引用
System.Windows.Forms.dll
WindowsFormsIntegration.dll
System.Windows.Forms.DataVisualization.dll
2..xaml添加命名空間
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:Chr="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"
3.WPF是不可以直接引用WinForm Chart,但可以托管在WindowsFormsHost
中使用,所以我們要添加一個宿主容器。
<WindowsFormsHost x:Name="WFHost_HistoryFlow" Margin="1"> <Chr:Chart x:Name="Chart_HistoryFlow" GetToolTipText="Chart_HistoryFlow_GetToolTipText" BackColor="WhiteSmoke" MouseWheel="Chart_HistoryFlow_MouseWheel"/> </WindowsFormsHost>
4.后台代碼.cs添加命名空間
using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting;
5.后台代碼
5.1私有變量
DataTable dataTable = new DataTable();
5.2 初始化
/// <summary> /// 設定Chart Control /// </summary> private void SetChart() { ChartArea ca = new ChartArea("ChartArea1"); this.Chart_HistoryFlow.ChartAreas.Add(ca); ChartArea ca_Pres = new ChartArea("ChartArea1"); this.Chart_HistoryPres.ChartAreas.Add(ca_Pres); ChartArea ca_Ratio = new ChartArea("ChartArea1"); this.Chart_HistoryRatio.ChartAreas.Add(ca_Ratio); //Processor System.Windows.Forms.DataVisualization.Charting.Legend lgFlow = new System.Windows.Forms.DataVisualization.Charting.Legend("Legend1"); lgFlow.IsTextAutoFit = true; lgFlow.Docking = Docking.Top; this.Chart_HistoryFlow.Legends.Add(lgFlow); System.Windows.Forms.DataVisualization.Charting.Legend lgPres = new System.Windows.Forms.DataVisualization.Charting.Legend("Legend1"); lgPres.IsTextAutoFit = true; lgPres.Docking = Docking.Top; this.Chart_HistoryPres.Legends.Add(lgPres); System.Windows.Forms.DataVisualization.Charting.Legend lgRatio = new System.Windows.Forms.DataVisualization.Charting.Legend("Legend1"); lgRatio.IsTextAutoFit = true; lgRatio.Docking = Docking.Top; this.Chart_HistoryRatio.Legends.Add(lgRatio); SetChartAutoBar(Chart_HistoryFlow); SetChartAutoBar(Chart_HistoryPres); SetChartAutoBar(Chart_HistoryRatio); } /// <summary> /// 設置折線圖游標 /// </summary> private void SetChartAutoBar(Chart chart) { //設置游標 chart.ChartAreas[0].CursorX.IsUserEnabled = true; chart.ChartAreas[0].CursorX.AutoScroll = true; chart.ChartAreas[0].CursorX.IsUserSelectionEnabled = true; //設置X軸是否可以縮放 chart.ChartAreas[0].AxisX.ScaleView.Zoomable = true; //將滾動內嵌到坐標軸中 chart.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true; // 設置滾動條的大小 chart.ChartAreas[0].AxisX.ScrollBar.Size = 10; // 設置滾動條的按鈕的風格,下面代碼是將所有滾動條上的按鈕都顯示出來 chart.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All; // 設置自動放大與縮小的最小量 chart.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = double.NaN; chart.ChartAreas[0].AxisX.ScaleView.SmallScrollMinSize = 1; }
5.3 事件
/// <summary> /// 歷史流量折線圖鼠標滾動 滾動條對應滑動 最小及最大數據位置停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Chart_HistoryFlow_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e) { //按住Ctrl,縮放 if ((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control) { if (e.Delta < 0) Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Size += 4; else Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Size -= 4; } //不按Ctrl,滾動 else { if (e.Delta < 0) { //當前位置+視圖長大於最大數據時停止 if (Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Position + Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Size < Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.ViewMaximum) Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Position += 4; } else { //當前位置小於最小數據時停止 if (Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Position > Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.ViewMinimum) Chart_HistoryFlow.ChartAreas[0].AxisX.ScaleView.Position -= 4; } } } /// <summary> /// 流量脈沖折線圖光標顯示詳細數據 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Chart_HistoryFlow_GetToolTipText(object sender, System.Windows.Forms.DataVisualization.Charting.ToolTipEventArgs e) { if (e.HitTestResult.ChartElementType == ChartElementType.DataPoint) { this.Cursor = System.Windows.Input.Cursors.Cross; int i = e.HitTestResult.PointIndex; string time = this.dataTable.Rows[i]["時間"].ToString(); string aFlow = this.dataTable.Rows[i]["A脈沖"].ToString(); string bFlow = this.dataTable.Rows[i]["B脈沖"].ToString(); string aPressure = this.dataTable.Rows[i]["A壓力"].ToString(); string bPressure = this.dataTable.Rows[i]["B壓力"].ToString(); string abRatio = this.dataTable.Rows[i]["AB比率"].ToString(); e.Text = $"時 間:{time}\r\nA脈沖:{aFlow}\r\nB脈沖:{bFlow}\r\nA壓力:{aPressure}\r\nB壓力:{bPressure}\r\nAB比率:{abRatio}"; } else { this.Cursor = System.Windows.Input.Cursors.Arrow; } }
5.4 往Chart中寫入數據
/// <summary> /// DataTable數據寫入Chart中 /// </summary> /// <param name="dataTable">包含數據的DataTable</param> /// <param name="chart">待寫入數據的Chart</param> public void DataTableToChart(DataTable dataTable, Chart chart,string title, string series1, string series2) { chart.Series.Clear(); //清空圖表中的內容 chart.Titles.Clear(); chart.Titles.Add(title);//添加標題 chart.DataSource = dataTable; Series aCodeSeries = chart.Series.Add(series1);//添加第一個表 aCodeSeries.ChartType = SeriesChartType.Line;//設為折線圖顯示 aCodeSeries.YValueMembers = series1;//y軸為數據 aCodeSeries.XValueMember = "時間"; Series bCodeSeries = chart.Series.Add(series2);//添加第二個表 bCodeSeries.ChartType = SeriesChartType.Line;//設為折線圖顯示 bCodeSeries.YValueMembers = series2; }
往DataTable中寫點數據,我的列名為"時間","A脈沖","B脈沖","A壓力","B壓力","AB比率"。
5.5顯示效果
OVER~撒花