using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Data;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms.DataVisualization.Charting;
namespace FLY.ControlLibrary
{
///
/// GraphScan.xaml 的交互逻辑
///
public partial class GraphScan : UserControl, INotifyPropertyChanged, IGraphBase2, IGraphBase
{
//设定数据统计范围
#region IGraphBase
#region 附加属性
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(GraphScan), new PropertyMetadata("Title"));
public string Title
{
get
{
return GetValue(TitleProperty) as string;
}
set
{
if (value != Title)
{
SetValue(TitleProperty, value);
NotifyPropertyChanged("Title");
}
}
}
public static readonly DependencyProperty Title2Property =
DependencyProperty.Register("Title2", typeof(string), typeof(GraphScan), new PropertyMetadata(""));
public string Title2
{
get
{
return GetValue(Title2Property) as string;
}
set
{
if (value != Title2)
{
SetValue(Title2Property, value);
NotifyPropertyChanged("Title2");
}
}
}
public static readonly DependencyProperty IsValidProperty =
DependencyProperty.Register("IsValid", typeof(bool), typeof(GraphScan), new PropertyMetadata(true));
public bool IsValid
{
get
{
return (bool)GetValue(IsValidProperty);
}
set
{
if (value != IsValid)
{
SetValue(IsValidProperty, value);
NotifyPropertyChanged("IsValid");
}
}
}
///
/// 计算结果
///
public static readonly DependencyProperty CalStateProperty =
DependencyProperty.Register("CalState", typeof(string), typeof(GraphScan), new PropertyMetadata(
"Max:null Min:null Avg:null 2σ:null",
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
})));
public string CalState
{
get
{
return (string)GetValue(CalStateProperty);
}
set
{
SetValue(CalStateProperty, value);
}
}
///
/// 空的数据,定义某个值为空,默认为 99999998
///
public static readonly DependencyProperty EmptyValueProperty =
DependencyProperty.Register("EmptyValue", typeof(int), typeof(GraphScan), new PropertyMetadata(
99999998,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
})));
public int EmptyValue
{
get
{
return (int)GetValue(EmptyValueProperty);
}
set
{
SetValue(EmptyValueProperty, value);
}
}
///
/// 放大倍数, 目标值= Target/放大倍数
///
public static readonly DependencyProperty MultiProperty =
DependencyProperty.Register("Multi", typeof(int), typeof(GraphScan), new PropertyMetadata(
100,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
})));
public int Multi
{
get
{
return (int)GetValue(MultiProperty);
}
set
{
SetValue(MultiProperty, value);
}
}
///
/// 图类型
///
public static readonly DependencyProperty ChartTypeProperty =
DependencyProperty.Register("ChartType", typeof(System.Windows.Forms.DataVisualization.Charting.SeriesChartType), typeof(GraphScan), new PropertyMetadata(
System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Column,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("ChartType");
})));
public System.Windows.Forms.DataVisualization.Charting.SeriesChartType ChartType
{
get
{
return (System.Windows.Forms.DataVisualization.Charting.SeriesChartType)GetValue(ChartTypeProperty);
}
set
{
SetValue(ChartTypeProperty, value);
}
}
///
/// 目标值
///
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(int), typeof(GraphScan), new PropertyMetadata(
3000,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("Target");
})));
public int Target
{
get
{
return (int)GetValue(TargetProperty);
}
set
{
SetValue(TargetProperty, value);
}
}
private int autotarget;
public int AutoTarget
{
get { return autotarget; }
set
{
if (autotarget != value)
{
autotarget = value;
NotifyPropertyChanged("AutoTarget");
}
}
}
///
/// 自动目标值
///
public static readonly DependencyProperty IsAutoTargetProperty =
DependencyProperty.Register("IsAutoTarget", typeof(bool), typeof(GraphScan), new PropertyMetadata(
false,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("IsAutoTarget");
})));
public bool IsAutoTarget
{
get
{
return (bool)GetValue(IsAutoTargetProperty);
}
set
{
SetValue(IsAutoTargetProperty, value);
}
}
///
/// 获取或设置指示是否将轴反转的标志
///
public static readonly DependencyProperty IsReversedProperty =
DependencyProperty.Register("IsReversed", typeof(bool), typeof(GraphScan), new PropertyMetadata(
false,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("IsReversed");
})));
public bool IsReversed
{
get
{
return (bool)GetValue(IsReversedProperty);
}
set
{
SetValue(IsReversedProperty, value);
}
}
///
/// 获取或设置 左右标示是否反转 的标志
///
public static readonly DependencyProperty LeftRightIsReversedProperty =
DependencyProperty.Register("LeftRightIsReversed", typeof(bool), typeof(GraphScan), new PropertyMetadata(
false,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("LeftRightIsReversed");
})));
///
/// 左右标示 反转
///
public bool LeftRightIsReversed
{
get
{
return (bool)GetValue(LeftRightIsReversedProperty);
}
set
{
SetValue(LeftRightIsReversedProperty, value);
}
}
///
/// 左右标示 可见
///
public static readonly DependencyProperty LeftRightIsVisableProperty =
DependencyProperty.Register("LeftRightIsVisable", typeof(bool), typeof(GraphScan), new PropertyMetadata(
false,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("LeftRightIsVisable");
})));
///
/// 左右标示 反转
///
public bool LeftRightIsVisable
{
get
{
return (bool)GetValue(LeftRightIsVisableProperty);
}
set
{
SetValue(LeftRightIsVisableProperty, value);
}
}
///
/// %显示
///
public static readonly DependencyProperty IsPercentProperty =
DependencyProperty.Register("IsPercent", typeof(bool), typeof(GraphScan), new PropertyMetadata(
false,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("IsPercent");
})));
public bool IsPercent
{
get
{
return (bool)GetValue(IsPercentProperty);
}
set
{
SetValue(IsPercentProperty, value);
}
}
///
/// 报警值
///
public static readonly DependencyProperty AlarmProperty =
DependencyProperty.Register("Alarm", typeof(int), typeof(GraphScan), new PropertyMetadata(
1000,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("Alarm");
})));
public int Alarm
{
get
{
return (int)GetValue(AlarmProperty);
}
set
{
SetValue(AlarmProperty, value);
}
}
///
/// Y轴是 Alarm 的N倍 默认3倍
///
public static readonly DependencyProperty YRangePercentProperty =
DependencyProperty.Register("YRangePercent", typeof(double), typeof(GraphScan), new PropertyMetadata(
3.0,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("YRangePercent");
})));
public double YRangePercent
{
get
{
return (double)GetValue(YRangePercentProperty);
}
set
{
SetValue(YRangePercentProperty, value);
}
}
///
/// 控制线
///
public static readonly DependencyProperty HasCtrlLineProperty =
DependencyProperty.Register("HasCtrlLine", typeof(bool), typeof(GraphScan), new PropertyMetadata(
false,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("HasCtrlLine");
})));
public bool HasCtrlLine
{
get
{
return (bool)GetValue(HasCtrlLineProperty);
}
set
{
SetValue(HasCtrlLineProperty, value);
}
}
///
/// 控制线
///
public static readonly DependencyProperty CtrlLineProperty =
DependencyProperty.Register("CtrlLine", typeof(int), typeof(GraphScan), new PropertyMetadata(
1000,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("CtrlLine");
})));
public int CtrlLine
{
get
{
return (int)GetValue(CtrlLineProperty);
}
set
{
SetValue(CtrlLineProperty, value);
}
}
///
/// 第一个分区号
///
public static readonly DependencyProperty FirstBoltNoProperty =
DependencyProperty.Register("FirstBoltNo", typeof(int), typeof(GraphScan), new PropertyMetadata(
0,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("FirstBoltNo");
})));
public int FirstBoltNo
{
get
{
return (int)GetValue(FirstBoltNoProperty);
}
set
{
SetValue(FirstBoltNoProperty, value);
}
}
///
///
///
public static readonly DependencyProperty FirstIndexProperty =
DependencyProperty.Register("FirstIndex", typeof(int), typeof(GraphScan), new PropertyMetadata(
0,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("FirstIndex");
})));
public int FirstIndex
{
get
{
return (int)GetValue(FirstIndexProperty);
}
set
{
SetValue(FirstIndexProperty, value);
}
}
///
///
///
public static readonly DependencyProperty LastIndexProperty =
DependencyProperty.Register("LastIndex", typeof(int), typeof(GraphScan), new PropertyMetadata(
49,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("LastIndex");
})));
public int LastIndex
{
get
{
return (int)GetValue(LastIndexProperty);
}
set
{
SetValue(LastIndexProperty, value);
}
}
///
/// 数据统计的开始
///
public static readonly DependencyProperty DataFirstProperty =
DependencyProperty.Register("DataFirst", typeof(int), typeof(GraphScan), new PropertyMetadata(
0,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("DataFirst");
})));
public int DataFirst
{
get
{
return (int)GetValue(DataFirstProperty);
}
set
{
SetValue(DataFirstProperty, value);
}
}
///
/// 数据统计的结束
///
public static readonly DependencyProperty DataLastProperty =
DependencyProperty.Register("DataLast", typeof(int), typeof(GraphScan), new PropertyMetadata(
49,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as GraphScan).NotifyPropertyChanged("DataLast");
})));
public int DataLast
{
get
{
return (int)GetValue(DataLastProperty);
}
set
{
SetValue(DataLastProperty, value);
}
}
#endregion
///
/// 数据源
///
private ObservableCollection _datasource;
public virtual ObservableCollection DataSource
{
get
{
return _datasource;
}
set
{
if (_datasource != null)
_datasource.CollectionChanged -= dataSource_CollectionChanged;
_datasource = value;
_datasource.CollectionChanged += dataSource_CollectionChanged;
mRefresh.UpdateData = true;
}
}
public event EventHandler ShowSettingDialogEvent;
#endregion
#region 刷新率控制
protected class Refresh
{
///
/// 控制刷新率
///
System.Windows.Threading.DispatcherTimer timer;
bool updatedata_flag = false;
bool updatey_flag = false;
bool updatex_flag = false;
bool updatecalx_flag = false;
///
/// 最快0.1s 刷新一次
///
TimeSpan REFRESH_RATE = TimeSpan.FromSeconds(0.1);
public Refresh(GraphScan graph)
{
timer = new System.Windows.Threading.DispatcherTimer();
timer.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (UpdateData)
{
UpdateData = false;
graph.DataBindAll2();
}
if (UpdateY)
{
UpdateY = false;
graph.UpdateAxisY();
}
if (UpdateX)
{
UpdateX = false;
graph.UpdateXRange();
}
if (UpdateCalX)
{
UpdateCalX = false;
graph.UpdateDataCalRange();
graph.UpdateCalState();
}
timer.Stop();
});
timer.Interval = REFRESH_RATE;
timer.Start();
}
public bool UpdateData
{
get { return updatedata_flag; }
set
{
updatedata_flag = value;
if (value)
{
if (!timer.IsEnabled)
timer.Start();
}
}
}
public bool UpdateY
{
get { return updatey_flag; }
set
{
updatey_flag = value;
if (value)
{
if (!timer.IsEnabled)
timer.Start();
}
}
}
public bool UpdateX
{
get { return updatex_flag; }
set
{
updatex_flag = value;
if (value)
{
if (!timer.IsEnabled)
timer.Start();
}
}
}
public bool UpdateCalX
{
get { return updatecalx_flag; }
set
{
updatecalx_flag = value;
if (value)
{
if (!timer.IsEnabled)
timer.Start();
}
}
}
}
protected Refresh mRefresh;
#endregion
public GraphScan()
{
InitializeComponent();
InitializeComponent2();
//this.DataContext = this;
grid_title.DataContext = this;
//this.rectangle.DataContext = this;
//this.run_title.DataContext = this;
//this.run_title2.DataContext = this;
//this.grid_left.DataContext = this;
//this.grid_right.DataContext = this;
PropertyChanged += new PropertyChangedEventHandler(GraphScan_PropertyChanged);
mRefresh = new Refresh(this);
SetDefault();
//Test();
}
void GraphScan_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//if (e.PropertyName == "AutoTarget")
//{
// if (IsAutoTarget)
// {
// mRefresh.UpdateY = true;
// mRefresh.UpdateData = true;
// }
//}
if ((e.PropertyName == "Target") ||
(e.PropertyName == "Alarm") ||
(e.PropertyName == "YRangePercent") ||
(e.PropertyName == "IsAutoTarget") ||
(e.PropertyName == "IsPercent") ||
(e.PropertyName == "AutoTarget"))
{
mRefresh.UpdateY = true;
mRefresh.UpdateData = true;
}
else if (e.PropertyName == "FirstBoltNo")
{
mRefresh.UpdateCalX = true;
mRefresh.UpdateX = true;
mRefresh.UpdateData = true;
}
else if (e.PropertyName == "FirstIndex" || e.PropertyName == "LastIndex")
{
mRefresh.UpdateX = true;
}
else if (e.PropertyName == "DataFirst" || e.PropertyName == "DataLast")
{
mRefresh.UpdateCalX = true;
}
else if (e.PropertyName == "ChartType")
{
UpdateChartType();
}
else if (e.PropertyName == "IsReversed")
{
chart1.ChartAreas[0].AxisX.IsReversed = IsReversed;
}
else if ((e.PropertyName == "HasCtrlLine") || (e.PropertyName == "CtrlLine"))
{
UpdateCtrlLine();
}
}
public virtual void UpdateChartType()
{
Series series1 = chart1.Series[0];
series1.ChartType = ChartType;
if (ChartType == SeriesChartType.Line)
{
series1.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
}
else
{
series1.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.None;
}
}
public void SetDefault()
{
NotifyPropertyChanged("Target");
NotifyPropertyChanged("TAlarm");
NotifyPropertyChanged("YRangePercent");
NotifyPropertyChanged("ChartType");
NotifyPropertyChanged("FirstBoltNo");
NotifyPropertyChanged("FirstIndex");
NotifyPropertyChanged("LastIndex");
NotifyPropertyChanged("DataFirst");
NotifyPropertyChanged("DataLast");
AutoTarget = Target;
}
protected virtual void Test()
{
ObservableCollection datasource = new ObservableCollection();
// Populate series data
Random random = new Random();
for (int i = 0; i < 40; i++)
{
datasource.Add(random.Next(3000) - 1500 + Target);
}
DataSource = datasource;
}
protected virtual void InitializeComponent2()
{
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
//
// chart1
//
chartArea1.AxisX.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
chartArea1.AxisX.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.AxisX.MajorGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.AxisX.IsMarksNextToAxis = false;
chartArea1.AxisX.Interval = 5;
chartArea1.AxisX.IsLabelAutoFit = true;
chartArea1.AxisX.LabelAutoFitStyle = LabelAutoFitStyles.DecreaseFont;
chartArea1.AxisY.LabelStyle.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
chartArea1.AxisY.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.AxisY.MajorGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
//this.chart1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(78)))), ((int)(((byte)(160)))), ((int)(((byte)(34)))));
//chartArea1.BackColor = this.chart1.BackColor;
//chartArea1.BackColor = System.Drawing.Color.Transparent;
//chartArea1.BackColor = System.Drawing.Color.OldLace;
//chartArea1.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.TopBottom;
//chartArea1.BackSecondaryColor = System.Drawing.Color.White;
chartArea1.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
chartArea1.BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
chartArea1.Name = "Default";
//chartArea1.Position.Height = 100;// 42F;
//chartArea1.Position.Width = 100;// 88F;
//chartArea1.Position.X = 0;// 3F;
//chartArea1.Position.Y = 0;// 10F;
//chartArea1.ShadowColor = System.Drawing.Color.Transparent;
this.chart1.ChartAreas.Add(chartArea1);
//legend1.BackColor = System.Drawing.Color.Transparent;
//legend1.Enabled = false;
//legend1.Font = new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
//legend1.IsTextAutoFit = false;
//legend1.Name = "Default";
//this.chart1.Legends.Add(legend1);
//this.chart1.Location = new System.Drawing.Point(16, 32);
this.chart1.Name = "chart1";
series1.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(26)))), ((int)(((byte)(59)))), ((int)(((byte)(105)))));
series1.BorderWidth = 2;
series1.ChartArea = chartArea1.Name;
//TODO
series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Column;
series1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(65)))), ((int)(((byte)(140)))), ((int)(((byte)(240)))));
series1.MarkerSize = 6;
//series1.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
series1.Name = "Series 1";
series1.ShadowColor = System.Drawing.Color.Black;
series1.ShadowOffset = 2;
series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Double;
this.chart1.Series.Add(series1);
this.chart1.BackColor = System.Drawing.Color.Transparent;
this.chart1.PrePaint += new System.EventHandler(Chart1_PrePaint);
}
protected virtual void SetCustomLabel(Axis axisY, double p, GridTickTypes gt, System.Drawing.Color c, bool ispercent, string message)
{
double r = axisY.Maximum - axisY.Minimum;
double f, t;
f = p + r / 2;
t = p - r / 2;
double target = (axisY.Maximum + axisY.Minimum) / 2;
CustomLabel customLabel;
string str;
if (!ispercent)
{
str = p.ToString("N1");
}
else
{
//百分比模式!!!!!!!
if (target == p)
{
str = p.ToString("N1");
}
else
{
double percent;
percent = ((p - target) / target) * 100;
str = percent.ToString("N1") + "%";
}
}
if(!string.IsNullOrEmpty(message))
str = message + " " + str;
customLabel = axisY.CustomLabels.Add(f, t, str);
customLabel.GridTicks = gt;
customLabel.ForeColor = c;
}
///
/// 获取实际应用的目标值,公差
///
///
///
///
///
protected void GetActualTargetAlarm(out double target, out double alarm, out double yrange, out bool ispercent)
{
double multi = Multi;
if (IsAutoTarget)
target = AutoTarget / multi;//AutoTarget 计算得到的平均值
else
target = Target / multi;
ispercent = IsPercent;
if ((ispercent) && (Target <= 0) || (Alarm < 0) || (target <= 0))
ispercent = false;
if (ispercent)
{
alarm = target * Alarm / Target;
}
else
{
alarm = Alarm / multi;
}
yrange = alarm * YRangePercent;
if ((alarm < 0.1) || (yrange < 0.3))
{
alarm = 0.1;
yrange = 0.3;
}
}
///
/// 与 Multi,Target,YRange,Alarm 相关
///
public virtual void UpdateAxisY()
{
double alarm;
double yrange;
double target;
bool ispercent;
GetActualTargetAlarm(out target, out alarm, out yrange, out ispercent);
Axis axisY = chart1.ChartAreas["Default"].AxisY;
axisY.Crossing = target;
// Set manual minimum and maximum values.
axisY.Minimum = target - yrange;
axisY.Maximum = target + yrange;
axisY.CustomLabels.Clear();
//中间目标值,肯定不以%显示
SetCustomLabel(axisY, target, GridTickTypes.All,System.Drawing.Color.Green, false, null);
//上下限
SetCustomLabel(axisY, target + alarm, GridTickTypes.All, System.Drawing.Color.DarkGoldenrod, ispercent, null);
SetCustomLabel(axisY, target - alarm, GridTickTypes.All, System.Drawing.Color.DarkGoldenrod, ispercent, null);
//2倍上下限
SetCustomLabel(axisY, target + alarm * 2, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null);
SetCustomLabel(axisY, target - alarm * 2, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null);
//显示范围数值
if ((yrange != alarm ) && (yrange != 2*alarm ))
{
SetCustomLabel(axisY, axisY.Minimum, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null);
SetCustomLabel(axisY, axisY.Maximum, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null);
}
//显示范围太小,多加纵坐标
if (yrange <= alarm)
{
SetCustomLabel(axisY, target - yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null);
SetCustomLabel(axisY, target + yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null);
}
}
///
/// 与 FirstBoltNo,DataFirst,DataLast 相关
///
public virtual void UpdateDataCalRange()
{
int firstBoltNo = FirstBoltNo;
int datafirst = DataFirst;
int datalast = DataLast;
if (datafirst > datalast)
{
int swap = datalast;
datalast = datafirst;
datafirst = swap;
}
System.Windows.Forms.DataVisualization.Charting.Axis axisX = chart1.ChartAreas["Default"].AxisX;
axisX.CustomLabels.Clear();
System.Windows.Forms.DataVisualization.Charting.CustomLabel customlabel
= new System.Windows.Forms.DataVisualization.Charting.CustomLabel(
datafirst + firstBoltNo, datalast + firstBoltNo, CalState, 1,
System.Windows.Forms.DataVisualization.Charting.LabelMarkStyle.LineSideMark);
axisX.CustomLabels.Add(customlabel);
}
///
/// 与 FirstBoltNo,FirstIndex,LastIndex 相关
///
public virtual void UpdateXRange()
{
int firstBoltNo = FirstBoltNo;
int first = FirstIndex;
int last = LastIndex;
if (first > last)
{
//交换
int swap = last;
last = first;
first = swap;
}
else if (first == last)
{
last = first + 10;
}
// Set manual minimum and maximum values.
chart1.ChartAreas["Default"].AxisX.Minimum = firstBoltNo + first;
chart1.ChartAreas["Default"].AxisX.Maximum = firstBoltNo + last;
}
public virtual void UpdateCtrlLine()
{
chart1.Invalidate();
}
protected virtual void Chart1_PrePaint(object sender, System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs e)
{
if (e.ChartElement is ChartArea)
{
ChartArea area = (ChartArea)e.ChartElement;
if (area.Name == "Default")
{
if (!HasCtrlLine)
return;
double c1 = ((double)(Target + CtrlLine)) / Multi;
double c2 = ((double)(Target - CtrlLine)) / Multi;
if (c1 > area.AxisY.Maximum || c2 < area.AxisY.Minimum)
return;
// Take Graphics object from chart
Graphics graph = e.ChartGraphics.Graphics;
// Convert X and Y values to screen position
c1 = e.ChartGraphics.GetPositionFromAxis(area.Name, AxisName.Y, c1);
c2 = e.ChartGraphics.GetPositionFromAxis(area.Name, AxisName.Y, c2);
double XMin = e.ChartGraphics.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Minimum);
double XMax = e.ChartGraphics.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum);
// Draw Maximum trangle
System.Drawing.Pen darkPen = new System.Drawing.Pen(System.Drawing.Color.LightPink,1);
System.Drawing.PointF[] points = new System.Drawing.PointF[2];
points[0].X = (float)XMin;
points[1].X = (float)XMax;
points[0].Y = points[1].Y = (float)c1;
// Convert relative coordinates to absolute coordinates.
points[0] = e.ChartGraphics.GetAbsolutePoint(points[0]);
points[1] = e.ChartGraphics.GetAbsolutePoint(points[1]);
graph.DrawLine(darkPen, points[0], points[1]);
points[0].X = (float)XMin;
points[1].X = (float)XMax;
points[0].Y = points[1].Y = (float)c2;
// Convert relative coordinates to absolute coordinates.
points[0] = e.ChartGraphics.GetAbsolutePoint(points[0]);
points[1] = e.ChartGraphics.GetAbsolutePoint(points[1]);
graph.DrawLine(darkPen, points[0], points[1]);
}
}
}
///
/// 与 Multi,EmptyValue,DataFirst,DataLast 相关
///
public virtual void UpdateCalState()
{
int emptyvalue = EmptyValue;
double multi = Multi;
if (DataSource == null)
{
goto _err;
}
int datafirst = DataFirst;
int datalast = DataLast;
if (datafirst > datalast)
{
int swap = datalast;
datalast = datafirst;
datafirst = swap;
}
if (datafirst < 0)
datafirst = 0;
if (datalast >= DataSource.Count())
datalast = DataSource.Count() - 1;
int datalen = datalast - datafirst + 1;
if(datafirst>=DataSource.Count())
{
goto _err;
}
if ((datafirst + datalen)>DataSource.Count())
{
datalen = DataSource.Count() - datafirst;
}
List datlist = DataSource.ToList().GetRange(datafirst,datalen);
string title;
var dats = from data in datlist where data!=emptyvalue select data;
if(dats.Count()==0)
{
goto _err;
}
else
{
AutoTarget = (int)dats.Average();
double avg = dats.Average() / multi;
double max = dats.Max()/multi;
double min = dats.Min()/multi;
double sum=0;
foreach(int dat in dats)
{
sum += Math.Pow(avg - (double)dat / multi, 2);
}
sum/=(dats.Count()-1);
double sigma=Math.Sqrt(sum);
if (IsPercent)
{
title = "Max:+" + ((max/avg * 100)-100).ToString("N1") + "% " +
"Min:-" + (100-(min / avg * 100)).ToString("N1") + "% " +
"Avg:" + avg.ToString("N1") + " " +
"2σ:" + (sigma/avg * 2 * 100).ToString("N1")+"%";
}
else
{
title = "Max:" + max.ToString("N1") + " " +
"Min:" + min.ToString("N1") + " " +
"Avg:" + avg.ToString("N1") + " " +
"2σ:" + (sigma * 2).ToString("N1");
}
}
goto _end;
_err:
//title = Properties.Resources.StrMax + ":" + "NULL " +
// Properties.Resources.StrMin+":"+"NULL "+
// Properties.Resources.StrAvg+":"+"NULL "+
// "3Sigma:"+"NULL ";
title = "Max:null Min:null Avg:null 2σ:null";
_end:
CalState = title;
UpdateDataCalRange();
//chart1.ChartAreas["Default"].AxisX.Title = title;
//chart1.ChartAreas["Default"].AxisX.TitleFont = new System.Drawing.Font("Times New Roman", 12, System.Drawing.FontStyle.Bold);
//chart1.ChartAreas["Default"].AxisX.TitleForeColor = System.Drawing.Color.Black;
}
protected virtual void UpdateOnePoint(int index)
{
double multi = Multi;
int emptyvalue = EmptyValue;
DataPoint point;
double v;
if (DataSource[index] == emptyvalue)
v = double.NaN;
else
v = DataSource[index] / multi;
if (index >= chart1.Series[0].Points.Count)
{
chart1.Series[0].Points.AddXY(
FirstBoltNo + index, v);
point = chart1.Series["Series 1"].Points[index];
}
else
{
point = chart1.Series["Series 1"].Points[index];
point.YValues[0] = v;
point.XValue = FirstBoltNo + index;
}
//设定空数据
if (double.IsNaN(point.YValues[0]))
{
point.IsEmpty = true;
System.Drawing.Color c = System.Drawing.Color.Transparent;
point.MarkerColor = c;
point.BorderColor = c;
point.Color = c;
}
else
{
point.IsEmpty = false;
System.Drawing.Color c;
double alarm;
double yrange;
double target;
bool ispercent;
GetActualTargetAlarm(out target, out alarm, out yrange, out ispercent);
double threshold1 = alarm * multi;
double threshold2 = threshold1 * 2;
target *= multi;
if ((DataSource[index] > (target + threshold2)) || (DataSource[index] < (target - threshold2)))
{
c = System.Drawing.Color.Red;
}
else if ((DataSource[index] > (target + threshold1)) || (DataSource[index] < (target - threshold1)))
{
c = System.Drawing.Color.Orange;
}
else
{
c = System.Drawing.Color.Green;
}
if (ChartType == SeriesChartType.Line)
{
point.MarkerColor = c;
point.BorderColor = chart1.Series["Series 1"].BorderColor;
point.Color = chart1.Series["Series 1"].Color;
}
else
{
point.MarkerColor = c;
point.BorderColor = c;
point.Color = c;
}
}
}
void DataBindAll2()
{
double multi = Multi;
int emptyvalue=EmptyValue;
UpdateCalState();
chart1.Series["Series 1"].Points.Clear();
if (DataSource != null)
{
for (int i = 0; i < DataSource.Count(); i++)
{
chart1.Series["Series 1"].Points.AddXY(
FirstBoltNo + i,
(double)DataSource.ElementAt(i) / multi);
UpdateOnePoint(i);
}
}
CheckDataSourceEmpty();
}
///
/// DataSource 里面的数据都是 EmptyValue 组成, 当修改数据时,应该clear ,再添加
///
private bool DataSourceIsEmpty = false;
///
/// 当一个数据都没有时,需要添加空数据
///
public void CheckDataSourceEmpty()
{
if ((DataSource == null) || (DataSource.Count() == 0))
{
chart1.Series["Series 1"].Points.Clear();
chart1.Series["Series 1"].Points.AddXY(FirstBoltNo, EmptyValue);
chart1.Series["Series 1"].Points[0].IsEmpty = true;
DataSourceIsEmpty = true;
}
else
{
DataSourceIsEmpty = false;
}
}
void dataSource_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
mRefresh.UpdateData = true;
}
public void Button_Click(object sender, RoutedEventArgs e)
{
if (ShowSettingDialogEvent != null)
ShowSettingDialogEvent(this, new EventArgs());
}
#region INotifyPropertyChanged 成员
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
class IsValidConverter : IValueConverter
{
#region IValueConverter 成员
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool isValid = (bool)value;
if (isValid)
return new SolidColorBrush(System.Windows.Media.Color.FromRgb(0x57, 0x9a, 0xab));
else
return new SolidColorBrush(System.Windows.Media.Color.FromRgb(237, 106, 0));
}
#endregion
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
class LeftRightConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values.Count() != 2)
return null;
if((!(values[0] is bool))||(!(values[1] is bool)))
return null;
bool leftright_isVisable = (bool)values[0];
bool leftright_IsReversed = (bool)values[1];
string flag = (string)parameter;
if (!leftright_isVisable)
return Visibility.Hidden;
else
{
if (flag == "LIsL")
{
if (leftright_IsReversed)
return Visibility.Hidden;
else
return Visibility.Visible;
}
else if (flag == "LIsR")
{
if (leftright_IsReversed)
return Visibility.Visible;
else
return Visibility.Hidden;
}
else if (flag == "RIsL")
{
if (leftright_IsReversed)
return Visibility.Visible;
else
return Visibility.Hidden;
}
else if (flag == "RIsR")
{
if (leftright_IsReversed)
return Visibility.Hidden;
else
return Visibility.Visible;
}
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}