diff --git a/BPASmartClient.SCADAControl/BPASmartClient.SCADAControl.csproj b/BPASmartClient.SCADAControl/BPASmartClient.SCADAControl.csproj
index 731a66c4..09391b18 100644
--- a/BPASmartClient.SCADAControl/BPASmartClient.SCADAControl.csproj
+++ b/BPASmartClient.SCADAControl/BPASmartClient.SCADAControl.csproj
@@ -8,6 +8,12 @@
+
+
+
+
+
+
@@ -35,6 +41,12 @@
+
+
+
+
+
+
diff --git a/BPASmartClient.SCADAControl/Converters/BoolToVisibilityConverter.cs b/BPASmartClient.SCADAControl/Converters/BoolToVisibilityConverter.cs
new file mode 100644
index 00000000..f50d25ff
--- /dev/null
+++ b/BPASmartClient.SCADAControl/Converters/BoolToVisibilityConverter.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Data;
+
+namespace BPASmartClient.SCADAControl.Converters
+{
+ [ValueConversion(typeof(bool), typeof(Visibility))]
+ public class BoolToVisibilityConverter : IValueConverter
+ {
+ static BoolToVisibilityConverter()
+ {
+ Instance = new BoolToVisibilityConverter();
+ }
+
+ public static BoolToVisibilityConverter Instance
+ {
+ get;
+ private set;
+ }
+
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return ((bool)value) ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/Converters/ControlTypeAttribute.cs b/BPASmartClient.SCADAControl/Converters/ControlTypeAttribute.cs
new file mode 100644
index 00000000..fdc08f98
--- /dev/null
+++ b/BPASmartClient.SCADAControl/Converters/ControlTypeAttribute.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.SCADAControl.Converters
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public class ControlTypeAttribute : Attribute
+ {
+ public string Group { get; set; }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/Converters/ItemsList.cs b/BPASmartClient.SCADAControl/Converters/ItemsList.cs
new file mode 100644
index 00000000..2203b480
--- /dev/null
+++ b/BPASmartClient.SCADAControl/Converters/ItemsList.cs
@@ -0,0 +1,37 @@
+using Microsoft.Toolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.SCADAControl.Converters
+{
+ ///
+ /// 因ObservableCollection无法序列化,继承并实例化一个
+ ///
+ public class ItemsList : ObservableCollection
+ {
+ public ItemsList()
+ {
+ AddCommand = new RelayCommand(AddItem);
+ DeleteCommand = new RelayCommand(DeleteItem);
+ }
+
+ private void DeleteItem(string obj)
+ {
+ if (!string.IsNullOrEmpty(obj))
+ Remove(obj);
+ }
+
+ public RelayCommand AddCommand { get; }
+ public RelayCommand DeleteCommand { get; }
+ private void AddItem(string txt)
+ {
+ if (!string.IsNullOrEmpty(txt))
+ Add(txt);
+ }
+
+ }
+}
diff --git a/BPASmartClient.SCADAControl/ArcGauge.cs b/BPASmartClient.SCADAControl/CustomerControls/ArcGauge.cs
similarity index 99%
rename from BPASmartClient.SCADAControl/ArcGauge.cs
rename to BPASmartClient.SCADAControl/CustomerControls/ArcGauge.cs
index e5ee39a2..145842bf 100644
--- a/BPASmartClient.SCADAControl/ArcGauge.cs
+++ b/BPASmartClient.SCADAControl/CustomerControls/ArcGauge.cs
@@ -16,7 +16,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
-namespace BPASmartClient.SCADAControl
+namespace BPASmartClient.SCADAControl.CustomerControls
{
///
/// 新测试仪表盘
diff --git a/BPASmartClient.SCADAControl/CustomerControls/DigitalNumber.cs b/BPASmartClient.SCADAControl/CustomerControls/DigitalNumber.cs
new file mode 100644
index 00000000..376333cf
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/DigitalNumber.cs
@@ -0,0 +1,62 @@
+using BPASmartClient.Compiler;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace BPASmartClient.SCADAControl.CustomerControls
+{
+ ///
+ /// 数字表
+ ///
+ public class DigitalNumber :Control, IExecutable
+ {
+ public DigitalNumber()
+ {
+ Width = 80;
+ Height = 30;
+ }
+ public string ControlType => "控件";
+
+ static DigitalNumber()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(DigitalNumber),new FrameworkPropertyMetadata(typeof(DigitalNumber)));
+ }
+
+ TextBlock text = null;
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ text = GetTemplateChild("line") as TextBlock;
+ }
+
+ public double NumberValue
+ {
+ get { return (double)GetValue(NumberValueProperty); }
+ set { SetValue(NumberValueProperty,value); }
+ }
+ public static readonly DependencyProperty NumberValueProperty =
+ DependencyProperty.Register("NumberValue",typeof(double),typeof(DigitalNumber),new UIPropertyMetadata(0.00d));
+
+ private bool isExecuteState;
+ public bool IsExecuteState
+ {
+ get { return isExecuteState; }
+ set
+ {
+ isExecuteState = value;
+ if (IsExecuteState)
+ {
+ Register();
+ }
+ }
+ }
+
+ public void Register()
+ {
+ }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/CustomerControls/GraphArrow.xaml b/BPASmartClient.SCADAControl/CustomerControls/GraphArrow.xaml
new file mode 100644
index 00000000..a0e5399b
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/GraphArrow.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/BPASmartClient.SCADAControl/CustomerControls/GraphArrow.xaml.cs b/BPASmartClient.SCADAControl/CustomerControls/GraphArrow.xaml.cs
new file mode 100644
index 00000000..77e7d0d4
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/GraphArrow.xaml.cs
@@ -0,0 +1,55 @@
+using BPASmartClient.Compiler;
+using BPASmartClient.SCADAControl;
+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.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;
+
+namespace BPASmartClient.SCADAControl.CustomerControls
+{
+ ///
+ /// 箭头
+ /// GraphArrow.xaml 的交互逻辑
+ ///
+ public partial class GraphArrow : UserControl, IExecutable
+ {
+ public GraphArrow()
+ {
+ InitializeComponent();
+ Width = 80;
+ Height = 80;
+ }
+
+ public string ControlType => "图形";
+
+ private bool isExecuteState;
+ public bool IsExecuteState
+ {
+ get { return isExecuteState; }
+ set
+ {
+ isExecuteState = value;
+ if (IsExecuteState)
+ {
+ IsEnabled = true;
+ Register();
+ Style = null;
+ }
+ }
+ }
+
+ public void Register()
+ {
+ }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/CustomerControls/GraphStar.xaml b/BPASmartClient.SCADAControl/CustomerControls/GraphStar.xaml
new file mode 100644
index 00000000..6b83c095
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/GraphStar.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/BPASmartClient.SCADAControl/CustomerControls/GraphStar.xaml.cs b/BPASmartClient.SCADAControl/CustomerControls/GraphStar.xaml.cs
new file mode 100644
index 00000000..b354c5c4
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/GraphStar.xaml.cs
@@ -0,0 +1,55 @@
+using BPASmartClient.Compiler;
+using BPASmartClient.SCADAControl;
+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.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;
+
+namespace BPASmartClient.SCADAControl.CustomerControls
+{
+ ///
+ /// 五角星
+ /// GraphStar.xaml 的交互逻辑
+ ///
+ public partial class GraphStar : UserControl, IExecutable
+ {
+ public GraphStar()
+ {
+ InitializeComponent();
+ Width = 100;
+ Height = 100;
+ }
+
+ public string ControlType => "图形";
+
+ private bool isExecuteState;
+ public bool IsExecuteState
+ {
+ get { return isExecuteState; }
+ set
+ {
+ isExecuteState = value;
+ if (IsExecuteState)
+ {
+ IsEnabled = true;
+ Register();
+ Style = null;
+ }
+ }
+ }
+
+ public void Register()
+ {
+ }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/CustomerControls/KnobButton.cs b/BPASmartClient.SCADAControl/CustomerControls/KnobButton.cs
new file mode 100644
index 00000000..26de890f
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/KnobButton.cs
@@ -0,0 +1,241 @@
+using BPASmartClient.Compiler;
+using BPASmartClient.SCADAControl;
+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.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace BPASmartClient.SCADAControl.CustomerControls
+{
+ ///
+ /// 旋转刻度
+ ///
+ public class KnobButton : Slider, IExecutable
+ {
+ static KnobButton()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(KnobButton), new FrameworkPropertyMetadata(typeof(KnobButton)));
+ }
+
+ public KnobButton()
+ {
+ SetCurrentValue(WidthProperty, 150d);
+ SetCurrentValue(HeightProperty, 150d);
+ SetCurrentValue(MaximumProperty, 100d);
+ MouseDown += Path_MouseDown;
+ MouseMove += Path_MouseMove;
+ MouseWheel += Path_MouseWheel;
+ MouseLeftButtonUp += KnobButton_MouseLeftButtonUp;
+ Update();
+ }
+
+ #region 设计需要
+ public string ControlType => "控件";
+
+ private bool isExecuteState;
+ public bool IsExecuteState
+ {
+ get { return isExecuteState; }
+ set
+ {
+ isExecuteState = value;
+ if (IsExecuteState)
+ Register();
+ }
+ }
+
+ ///
+ /// 注册需要处理的事件
+ ///
+ public void Register()
+ {
+ ValueChanged += KnobButton_ValueChanged; ;
+ }
+
+ private void KnobButton_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ Config.GetInstance().RunJsScipt(ValueChangedExecute);
+ }
+ #endregion
+
+ #region 绘制
+ private void InitTick()
+ {
+ // 画大刻度
+ for (int i = 0; i < 11; i++)
+ {
+ Line line = new Line();
+ line.X1 = 0;
+ line.Y1 = 0;
+ line.X2 = 0;
+ line.Y2 = 12;
+ line.Stroke = Brushes.Gray;
+ line.StrokeThickness = 2;
+ line.HorizontalAlignment = HorizontalAlignment.Center;
+ line.RenderTransformOrigin = new Point(0.5, 0.5);
+ line.RenderTransform = new RotateTransform() { Angle = -140 + i * 28 };
+ bdGrid.Children.Add(line);
+ }
+
+ // 画小刻度
+ for (int i = 0; i < 10; i++)
+ {
+ var start = -140 + 28 * i + 2.8;
+ for (int j = 0; j < 9; j++)
+ {
+ Line line = new Line();
+ line.X1 = 0;
+ line.Y1 = 0;
+ line.X2 = 0;
+ line.Y2 = 6;
+ line.Stroke = Brushes.Gray;
+ line.StrokeThickness = 1;
+ line.HorizontalAlignment = HorizontalAlignment.Center;
+ line.RenderTransformOrigin = new Point(0.5, 0.5);
+ line.RenderTransform = new RotateTransform() { Angle = start + j * 2.8 };
+ bdGrid.Children.Add(line);
+ }
+ }
+ }
+ #endregion
+ protected override void OnValueChanged(double oldValue, double newValue)
+ {
+ base.OnValueChanged(oldValue, newValue);
+ Update();
+ }
+
+ protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
+ {
+ base.OnMaximumChanged(oldMaximum, newMaximum);
+ Update();
+ }
+
+ protected override void OnMinimumChanged(double oldMinimum, double newMinimum)
+ {
+ base.OnMinimumChanged(oldMinimum, newMinimum);
+ Update();
+ }
+
+ public string ValueChangedExecute
+ {
+ get { return (string)GetValue(ValueChangedExecuteProperty); }
+ set { SetValue(ValueChangedExecuteProperty, value); }
+ }
+ public static readonly DependencyProperty ValueChangedExecuteProperty =
+ DependencyProperty.Register("ValueChangedExecute", typeof(string), typeof(KnobButton), new PropertyMetadata(string.Empty));
+
+ public int Step
+ {
+ get { return (int)GetValue(StepProperty); }
+ set { SetValue(StepProperty, value); }
+ }
+ public static readonly DependencyProperty StepProperty =
+ DependencyProperty.Register("Step", typeof(int), typeof(KnobButton), new PropertyMetadata(1));
+
+ RotateTransform rotatevalue;
+ Grid bdGrid;
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ rotatevalue = GetTemplateChild("rotatevalue") as RotateTransform;
+ bdGrid = GetTemplateChild("bdGrid") as Grid;
+ Update();
+ InitTick();
+ }
+
+ private void Update()
+ {
+ if (rotatevalue == null) return;
+ double perangle = 280 / (Maximum - Minimum);
+ double angle = (perangle * (Value - Minimum)) + 40;
+
+ DoubleAnimation da = new DoubleAnimation();
+ da.Duration = new Duration(TimeSpan.FromMilliseconds(350));
+ da.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
+ da.To = angle;
+
+ rotatevalue.Angle = angle;
+ rotatevalue.BeginAnimation(RotateTransform.AngleProperty, da);
+ }
+
+ Point lastpoint;
+ private void Path_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Released) return;
+
+ CaptureMouse();
+ Point point = e.GetPosition(this);
+ double xmove = point.X - lastpoint.X;
+ double ymove = point.Y - lastpoint.Y;
+
+ double changeValue = (xmove + ymove) / 10 * Step;
+ if ((changeValue + Value) > Maximum)
+ {
+ if (Value < Maximum)
+ {
+ Value = Maximum;
+ }
+ return;
+ }
+
+ if ((changeValue + Value) < Minimum)
+ {
+ if (Value > Minimum)
+ {
+ Value = Minimum;
+ }
+ return;
+ }
+
+ Value = changeValue + Value;
+ lastpoint = point;
+ }
+
+ private void Path_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Released) return;
+ lastpoint = e.GetPosition(this);
+ }
+
+ private void KnobButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ ReleaseMouseCapture();
+ }
+
+ private void Path_MouseWheel(object sender, MouseWheelEventArgs e)
+ {
+ double changeValue = (e.Delta / 120) * Step;
+ if ((changeValue + Value) > Maximum)
+ {
+ if (Value < Maximum)
+ {
+ Value = Maximum;
+ }
+ return;
+ }
+
+ if ((changeValue + Value) < Minimum)
+ {
+ if (Value > Minimum)
+ {
+ Value = Minimum;
+ }
+ return;
+ }
+
+ Value = Value + changeValue;
+ Update();
+ }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/NewConveyorBelt.xaml b/BPASmartClient.SCADAControl/CustomerControls/NewConveyorBelt.xaml
similarity index 94%
rename from BPASmartClient.SCADAControl/NewConveyorBelt.xaml
rename to BPASmartClient.SCADAControl/CustomerControls/NewConveyorBelt.xaml
index 7d1da941..bb22bb75 100644
--- a/BPASmartClient.SCADAControl/NewConveyorBelt.xaml
+++ b/BPASmartClient.SCADAControl/CustomerControls/NewConveyorBelt.xaml
@@ -1,9 +1,9 @@
-
+ /// 滚筒线
/// NewConveyorBelt.xaml 的交互逻辑
///
public partial class NewConveyorBelt : UserControl, IExecutable
diff --git a/BPASmartClient.SCADAControl/CustomerControls/NumberBox.cs b/BPASmartClient.SCADAControl/CustomerControls/NumberBox.cs
new file mode 100644
index 00000000..bbde7726
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/NumberBox.cs
@@ -0,0 +1,370 @@
+using BPASmartClient.Compiler;
+using BPASmartClient.SCADAControl;
+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.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;
+
+namespace BPASmartClient.SCADAControl.CustomerControls
+{
+ public class NumberBox : TextBox, IExecutable
+ {
+ static NumberBox()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(NumberBox), new FrameworkPropertyMetadata(typeof(NumberBox)));
+
+ FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(CURVALUE, new PropertyChangedCallback(OnCurValueChanged));
+ CurValueProperty = DependencyProperty.Register("CurValue", typeof(double), typeof(NumberBox), metadata);
+
+ metadata = new FrameworkPropertyMetadata(MINVALUE, new PropertyChangedCallback(OnMinValueChanged));
+ MinValueProperty = DependencyProperty.Register("MinValue", typeof(double), typeof(NumberBox), metadata);
+
+ metadata = new FrameworkPropertyMetadata(MAXVALUE, new PropertyChangedCallback(OnMaxValueChanged));
+ MaxValueProperty = DependencyProperty.Register("MaxValue", typeof(double), typeof(NumberBox), metadata);
+
+ metadata = new FrameworkPropertyMetadata(DIGITS, new PropertyChangedCallback(OnDigitsChanged));
+ DigitsProperty = DependencyProperty.Register("Digits", typeof(int), typeof(NumberBox), metadata);
+ }
+ public string ControlType => "控件";
+
+ public NumberBox()
+ {
+ Width = 80;
+ Height = 30;
+ CurValue = 0.01;
+ Digits = 2;
+
+ VerticalContentAlignment = VerticalAlignment.Center;
+
+ Style = Application.Current.Resources["DesignNumberBox"] as Style;//FindResource("DesignNumberBox") as Style;
+
+ this.TextChanged += NumberBox_TextChanged;
+ this.PreviewKeyDown += NumberBox_KeyDown;
+ this.LostFocus += NumberBox_LostFocus;
+ DataObject.AddPastingHandler(this, NumberBox_Pasting);
+ Focusable = false;
+ }
+
+ private bool isExecuteState;
+ public bool IsExecuteState
+ {
+ get { return isExecuteState; }
+ set
+ {
+ isExecuteState = value;
+ if (IsExecuteState)
+ {
+ IsEnabled = true;
+ Register();
+ Style = null;
+ Focusable = true;
+ }
+ }
+ }
+
+ public void Register()
+ {
+ }
+
+ #region DependencyProperty
+ private const double CURVALUE = 0; //当前值
+ private const double MINVALUE = double.MinValue; //最小值
+ private const double MAXVALUE = double.MaxValue; //最大值
+ private const int DIGITS = 15; //小数点精度
+
+ public static readonly DependencyProperty CurValueProperty;
+ public static readonly DependencyProperty MinValueProperty;
+ public static readonly DependencyProperty MaxValueProperty;
+ public static readonly DependencyProperty DigitsProperty;
+
+ public double CurValue
+ {
+ get
+ {
+ return (double)GetValue(CurValueProperty);
+ }
+ set
+ {
+ double v = value;
+ if (value < MinValue)
+ {
+ v = MinValue;
+ }
+ else if (value > MaxValue)
+ {
+ v = MaxValue;
+ }
+ v = Math.Round(v, Digits);
+
+ SetValue(CurValueProperty, v);
+ // if do not go into OnCurValueChanged then force update ui
+ if (v != value)
+ {
+ this.Text = v.ToString();
+ }
+ }
+ }
+ public double MinValue
+ {
+ get
+ {
+ return (double)GetValue(MinValueProperty);
+ }
+ set
+ {
+ SetValue(MinValueProperty, value);
+ }
+ }
+ public double MaxValue
+ {
+ get
+ {
+ return (double)GetValue(MaxValueProperty);
+ }
+ set
+ {
+ SetValue(MaxValueProperty, value);
+ }
+ }
+ public int Digits
+ {
+ get
+ {
+ return (int)GetValue(DigitsProperty);
+ }
+ set
+ {
+ int digits = value;
+ if (digits <= 0)
+ {
+ digits = 0;
+ }
+ if (digits > 15)
+ {
+ digits = 15;
+ }
+ SetValue(DigitsProperty, value);
+ }
+ }
+
+ private static void OnCurValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ double value = (double)e.NewValue;
+ NumberBox numericBox = (NumberBox)sender;
+ numericBox.Text = value.ToString();
+ }
+ private static void OnMinValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ double minValue = (double)e.NewValue;
+ NumberBox numericBox = (NumberBox)sender;
+ numericBox.MinValue = minValue;
+ }
+ private static void OnMaxValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ double maxValue = (double)e.NewValue;
+ NumberBox numericBox = (NumberBox)sender;
+ numericBox.MaxValue = maxValue;
+ }
+ private static void OnDigitsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+ {
+ int digits = (int)e.NewValue;
+ NumberBox numericBox = (NumberBox)sender;
+ numericBox.CurValue = Math.Round(numericBox.CurValue, digits);
+ numericBox.MinValue = Math.Round(numericBox.MinValue, digits);
+ numericBox.MaxValue = Math.Round(numericBox.MaxValue, digits);
+ }
+ #endregion
+
+
+ void NumberBox_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ NumberBox numericBox = sender as NumberBox;
+ if (string.IsNullOrEmpty(numericBox.Text))
+ {
+ return;
+ }
+
+ TrimZeroStart();
+
+ double value = MinValue;
+ if (!Double.TryParse(numericBox.Text, out value))
+ {
+ return;
+ }
+
+ if (value != this.CurValue)
+ {
+ this.CurValue = value;
+ }
+ }
+
+ void NumberBox_KeyDown(object sender, KeyEventArgs e)
+ {
+ Key key = e.Key;
+ if (IsControlKeys(key))
+ {
+ return;
+ }
+ else if (IsDigit(key))
+ {
+ return;
+ }
+ else if (IsSubtract(key)) //-
+ {
+ TextBox textBox = sender as TextBox;
+ string str = textBox.Text;
+ if (str.Length > 0 && textBox.SelectionStart != 0)
+ {
+ e.Handled = true;
+ }
+ }
+ else if (IsDot(key)) //point
+ {
+ if (this.Digits > 0)
+ {
+ TextBox textBox = sender as TextBox;
+ string str = textBox.Text;
+ if (str.Contains('.') || str == "-")
+ {
+ e.Handled = true;
+ }
+ }
+ else
+ {
+ e.Handled = true;
+ }
+ }
+ else
+ {
+ e.Handled = true;
+ }
+ }
+
+ void NumberBox_LostFocus(object sender, RoutedEventArgs e)
+ {
+ NumberBox numericBox = sender as NumberBox;
+ if (string.IsNullOrEmpty(numericBox.Text))
+ {
+ numericBox.Text = this.CurValue.ToString();
+ }
+ }
+
+ private void NumberBox_Pasting(object sender, DataObjectPastingEventArgs e)
+ {
+ e.CancelCommand();
+ }
+
+ private static readonly List _controlKeys = new List
+ {
+ Key.Back,
+ Key.CapsLock,
+ Key.Down,
+ Key.End,
+ Key.Enter,
+ Key.Escape,
+ Key.Home,
+ Key.Insert,
+ Key.Left,
+ Key.PageDown,
+ Key.PageUp,
+ Key.Right,
+ Key.Tab,
+ Key.Up
+ };
+ public static bool IsControlKeys(Key key)
+ {
+ return _controlKeys.Contains(key);
+ }
+
+ public static bool IsDigit(Key key)
+ {
+ bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
+ bool retVal;
+ if (key >= Key.D0 && key <= Key.D9 && !shiftKey)
+ {
+ retVal = true;
+ }
+ else
+ {
+ retVal = key >= Key.NumPad0 && key <= Key.NumPad9;
+ }
+ return retVal;
+ }
+
+
+ public static bool IsDot(Key key)
+ {
+ bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
+ bool flag = false;
+ if (key == Key.Decimal)
+ {
+ flag = true;
+ }
+ if (key == Key.OemPeriod && !shiftKey)
+ {
+ flag = true;
+ }
+ return flag;
+ }
+ public static bool IsSubtract(Key key)
+ {
+ bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
+ bool flag = false;
+ if (key == Key.Subtract)
+ {
+ flag = true;
+ }
+ if (key == Key.OemMinus && !shiftKey)
+ {
+ flag = true;
+ }
+ return flag;
+ }
+
+ private void TrimZeroStart()
+ {
+ if (this.Text.Length == 1)
+ {
+ return;
+ }
+ string resultText = this.Text;
+ int zeroCount = 0;
+ foreach (char c in this.Text)
+ {
+ if (c == '0') { zeroCount++; }
+ else { break; }
+ }
+ if (zeroCount == 0)
+ {
+ return;
+ }
+
+ if (this.Text.Contains('.'))
+ {
+ if (this.Text[zeroCount] != '.')
+ {
+ resultText = this.Text.TrimStart('0');
+ }
+ else if (zeroCount > 1)
+ {
+ resultText = this.Text.Substring(zeroCount - 1);
+ }
+ }
+ else if (zeroCount > 0)
+ {
+ resultText = this.Text.TrimStart('0');
+ }
+ }
+
+ }
+}
diff --git a/BPASmartClient.SCADAControl/Silos.xaml b/BPASmartClient.SCADAControl/CustomerControls/Silos.xaml
similarity index 98%
rename from BPASmartClient.SCADAControl/Silos.xaml
rename to BPASmartClient.SCADAControl/CustomerControls/Silos.xaml
index 704d6563..338cc6f7 100644
--- a/BPASmartClient.SCADAControl/Silos.xaml
+++ b/BPASmartClient.SCADAControl/CustomerControls/Silos.xaml
@@ -1,4 +1,4 @@
-
/// Silos.xaml 的交互逻辑
diff --git a/BPASmartClient.SCADAControl/CustomerControls/StatusLight.cs b/BPASmartClient.SCADAControl/CustomerControls/StatusLight.cs
new file mode 100644
index 00000000..a23c6541
--- /dev/null
+++ b/BPASmartClient.SCADAControl/CustomerControls/StatusLight.cs
@@ -0,0 +1,102 @@
+using BPASmartClient.Compiler;
+using BPASmartClient.SCADAControl;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+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;
+
+namespace BPASmartClient.SCADAControl.CustomerControls
+{
+ ///
+ /// 状态标志
+ ///
+ public class StatusLight : Control, IExecutable
+ {
+ public StatusLight()
+ {
+ Width = 80;
+ Height = 80;
+ }
+ public string ControlType => "控件";
+
+ static StatusLight()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(StatusLight), new FrameworkPropertyMetadata(typeof(StatusLight)));
+ }
+
+ private bool isExecuteState;
+ public bool IsExecuteState
+ {
+ get { return isExecuteState; }
+ set
+ {
+ isExecuteState = value;
+ if (IsExecuteState)
+ {
+ Register();
+ }
+ }
+ }
+
+ ///
+ /// 状态值
+ ///
+ [Category("值设定")]
+ public int StatusValue
+ {
+ get { return (int)GetValue(StatusValueProperty); }
+ set { SetValue(StatusValueProperty, value); }
+ }
+ public static readonly DependencyProperty StatusValueProperty =
+ DependencyProperty.Register("StatusValue", typeof(int), typeof(StatusLight), new UIPropertyMetadata(0, OnStatusChanged));
+
+ private static void OnStatusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as StatusLight).Refresh();
+
+ private void Refresh()
+ {
+ if (image != null)
+ {
+ switch (StatusValue)
+ {
+ case 0:
+ image.Source = new BitmapImage(new Uri("pack://application:,,,/Images/State0.png", UriKind.Absolute));
+ break;
+ case -1:
+ image.Source = new BitmapImage(new Uri("pack://application:,,,/Images/State11.png", UriKind.Absolute));
+ break;
+ case 1:
+ image.Source = new BitmapImage(new Uri("pack://application:,,,/Images/State1.png", UriKind.Absolute));
+ break;
+ case 2:
+ image.Source = new BitmapImage(new Uri("pack://application:,,,/Images/State2.png", UriKind.Absolute));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ Image image;
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ image = GetTemplateChild("ima") as Image;
+ Refresh();
+ }
+
+ public void Register()
+ {
+ }
+ }
+}
diff --git a/BPASmartClient.SCADAControl/SwitchButton.cs b/BPASmartClient.SCADAControl/CustomerControls/SwitchButton.cs
similarity index 97%
rename from BPASmartClient.SCADAControl/SwitchButton.cs
rename to BPASmartClient.SCADAControl/CustomerControls/SwitchButton.cs
index fc51b708..679f53f6 100644
--- a/BPASmartClient.SCADAControl/SwitchButton.cs
+++ b/BPASmartClient.SCADAControl/CustomerControls/SwitchButton.cs
@@ -17,8 +17,11 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
-namespace BPASmartClient.SCADAControl
+namespace BPASmartClient.SCADAControl.CustomerControls
{
+ ///
+ /// 开关button
+ ///
[TemplatePart(Name = ELLIPSE, Type = typeof(FrameworkElement))]
[TemplatePart(Name = TranslateX, Type = typeof(TranslateTransform))]
public class SwitchButton : ToggleButton, IExecutable
diff --git a/BPASmartClient.SCADAControl/TheButton.xaml b/BPASmartClient.SCADAControl/CustomerControls/TheButton.xaml
similarity index 86%
rename from BPASmartClient.SCADAControl/TheButton.xaml
rename to BPASmartClient.SCADAControl/CustomerControls/TheButton.xaml
index a02e50c1..e5aa9711 100644
--- a/BPASmartClient.SCADAControl/TheButton.xaml
+++ b/BPASmartClient.SCADAControl/CustomerControls/TheButton.xaml
@@ -1,4 +1,4 @@
-