using CommunityToolkit.Mvvm.Input; using FLY.Thick.Base.Common; using FLY.Thick.Base.IService; using FLY.Thick.Base.Server; using LiveCharts; using LiveCharts.Defaults; using LiveCharts.Wpf; using Misc; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using Unity; namespace FLY.Thick.Base.UI { /// <summary> /// Page_BorderSearch.xaml 的交互逻辑 /// </summary> public partial class PgBorderSearch : Page { PgBorderSearchVm viewModel; IUnityContainer container; public PgBorderSearch() { InitializeComponent(); if (System.ComponentModel.LicenseManager.UsageMode != System.ComponentModel.LicenseUsageMode.Runtime) return; this.Loaded += UcGridGraph_Loaded; this.Unloaded += UcGridGraph_Unloaded; } private void UcGridGraph_Unloaded(object sender, RoutedEventArgs e) { viewModel.DisposeBinding(); } private void UcGridGraph_Loaded(object sender, RoutedEventArgs e) { viewModel.SetBinding(); } [InjectionMethod] public void Init( IUnityContainer container, IBorderSearchService borderSearch, IInitParamService initParamService, ITDGageService gageService) { this.container = container; container.BuildUp(mircoGage); viewModel = new PgBorderSearchVm(); viewModel.Init(borderSearch, initParamService, gageService, chart); this.DataContext = viewModel; } } public class IntConverter : IValueConverter { #region IValueConverter 成员 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { try { int v = (int)value; if (Misc.MyBase.ISVALIDATA(v)) return v.ToString(); else return "null"; } catch { return "null"; } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { try { int v; if (int.TryParse(value as string, out v)) { return v; } else { return Misc.MyBase.NULL_VALUE; } } catch { return Misc.MyBase.NULL_VALUE; } } #endregion } public class PgBorderSearchVm : INotifyPropertyChanged { #region 延时推送 MARKNO const int MARKNO_UPDATE_BORDER = 0; const int MARKNO_UPDATE_DATAS = 1; #endregion public event PropertyChangedEventHandler PropertyChanged; #region 曲线 /// <summary> /// 图表放大辅助器 /// </summary> public CartesianChartZoomInHelper ZoomInHelper { get; private set; } public Func<double, string> XFormatter { get; private set; } public Func<double, string> YFormatter { get; private set; } public ChartValues<ObservablePoint> Values { get; } = new ChartValues<ObservablePoint>(); /// <summary> /// 左边界 开始位置 /// </summary> public int Sensor0AtBorderBegin { get; set; } /// <summary> /// 左边界 宽度 /// </summary> public int Sensor0AtBorderWidth { get; set; } /// <summary> /// 右边界 开始位置 /// </summary> public int Sensor1AtBorderBegin { get; set; } /// <summary> /// 右边 宽度 /// </summary> public int Sensor1AtBorderWidth { get; set; } #endregion #region 参数 /// <summary> /// 启动与否 /// </summary> public bool Enable { get; set; } /// <summary> /// 单一材料 /// </summary> public bool IsOneMaterial { get; set; } /// <summary> /// 边界拐点检测,找到的边界更加精确 /// </summary> public bool IsBreakDetect { get; set; } /// <summary> /// 有限范围 /// </summary> public Range Valid { get; set; } /// <summary> /// 手动设置温修AD值 /// </summary> public bool TempADBySet { set; get; } /// <summary> /// 温修AD值 /// </summary> public int TempAD { get; set; } /// <summary> /// AD超过了范围, 就认为开始找到边界 /// </summary> public int TempRange { get; set; } /// <summary> /// 温修范围是温修的百分比 /// </summary> public bool IsTempRangeByPercent { get; set; } /// <summary> /// 温修范围百分比 /// </summary> public double TempRangePercent { get; set; } /// <summary> /// 有滤波器,只有非空的连续N个pos以上,才开始算边界开始 /// </summary> public int N { get; set; } /// <summary> /// 探头直径,单位脉冲, 膜宽 = 边界范围 - 探头直径 /// </summary> public int SensorWidth { get; set; } /// <summary> /// 找到边界后,边界 + 探头半径 + N2个脉冲。 这个是数据有效的开始 /// </summary> public int N2 { get; set; } /// <summary> /// 记录两个边界以后扫描,以它们再外扩N3个脉冲,作为扫描范围 /// </summary> public int N3 { get; set; } #endregion #region Command public RelayCommand ApplyCmd { get; private set; } #endregion public int PosOfGrid { get; set; } = 20; public double Mmpp { get; set; } = 0.0943; public int PosLength { get; set; } = 20000; /// <summary> /// grid数据量 /// </summary> public int GridLen => PosLength / PosOfGrid; public Misc.DIRECTION Direction { get; private set; } = DIRECTION.FIX; public IBorderSearchService BorderSearchService => borderSearch; public IInitParamService InitParamService => initParam; #region 注入的对象 DynArea dynArea; CartesianChart chart; IBorderSearchService borderSearch; IInitParamService initParam; #endregion BorderSearchGetViewReponse getViewReponse; Dictionary<object, List<Misc.BindingOperations.PropertyChangedEventContexts>> bindingConexts = new Dictionary<object, List<Misc.BindingOperations.PropertyChangedEventContexts>>(); /// <summary> /// 数据已经绑定了 /// </summary> bool isBinding; public PgBorderSearchVm() { ApplyCmd = new RelayCommand(Apply); ZoomInHelper = new CartesianChartZoomInHelper(); ZoomInHelper.XRangeSlider.SliderMax = 1000; ZoomInHelper.XRangeSlider.SliderMin = 0; ZoomInHelper.XRangeSlider.MinRange = 10; ZoomInHelper.YRangeSlider.SliderMax = 66000; ZoomInHelper.YRangeSlider.SliderMin = -1000; ZoomInHelper.YRangeSlider.MinRange = 100; XFormatter = (x) => { int pos = (int)x; int mm = (int)(pos * Mmpp); return $"{pos}\n{mm}mm"; }; YFormatter = (y) => { return $"{y}"; }; } public void Init( IBorderSearchService borderSearch, IInitParamService initParamService, ITDGageService gageService, CartesianChart chart) { this.borderSearch = borderSearch; this.initParam = initParamService; dynArea = gageService.DynArea; this.chart = chart; SetBinding(); } /// <summary> /// 参数绑定 /// </summary> public void SetBinding() { if (isBinding) return; isBinding = true; //下面全部event保存在bindingConexts Misc.BindingOperations.StartMarkdownEvents(bindingConexts); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.Enable), this, nameof(Enable)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.IsOneMaterial), this, nameof(IsOneMaterial)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.IsBreakDetect), this, nameof(IsBreakDetect)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.Valid) ,this, () => { Valid = new Range(borderSearch.Valid); }); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.TempADBySet), this, nameof(TempADBySet)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.TempAD), this, nameof(TempAD)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.TempRange), this, nameof(TempRange)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.IsTempRangeByPercent), this, nameof(IsTempRangeByPercent)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.TempRangePercent), this, nameof(TempRangePercent)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.N), this, nameof(N)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.SensorWidth), this, nameof(SensorWidth)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.N2), this, nameof(N2)); Misc.BindingOperations.SetBinding(borderSearch, nameof(borderSearch.N3), this, nameof(N3)); Misc.BindingOperations.SetBinding(initParam, nameof(initParam.PosLength), this, nameof(PosLength)); Misc.BindingOperations.SetBinding(initParam, nameof(initParam.PosOfGrid), this, nameof(PosOfGrid)); Misc.BindingOperations.SetBinding(initParam, nameof(initParam.Encoder1_mmpp), this, nameof(Mmpp)); Misc.BindingOperations.SetBinding(this, nameof(PosLength), this, () => { ZoomInHelper.XRangeSlider.SliderMax = PosLength; }); //备份event完毕, 必须关闭记录 Misc.BindingOperations.StopMarkdownEvents(); ZoomInHelper.Init(chart); borderSearch.PropertyChanged += MborderSearch_PropertyChanged; getView(); } /// <summary> /// 解除绑定 /// </summary> public void DisposeBinding() { if (!isBinding)//已经解除绑定了 return; isBinding = false; //释放全部 event Misc.BindingOperations.DisposeEventTargetObject(bindingConexts); ZoomInHelper.DisposeBinding(); borderSearch.PropertyChanged -= MborderSearch_PropertyChanged; } private void MborderSearch_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(BorderSearch.UpdateTime)) { getView(); } } void getView() { borderSearch.GetView((asyncContext, retData) => { var response = retData as BorderSearchGetViewReponse; if (response == null) return; this.getViewReponse = response; this.Direction = getViewReponse.direction; int[] grid = getViewReponse.dat; if (grid == null) return; int posOfGrid = getViewReponse.posOfGrid; var thk0s = grid.Select((ad, index) => { int pos = (response.gridBegin + index) * posOfGrid; double ad2 = Misc.MyBase.ISVALIDATA(ad) ? ad : double.NaN; ObservablePoint point = new ObservablePoint(pos, ad2); return point; }); Values.Clear(); Values.AddRange(thk0s); UpdateRange(); Sensor0AtBorderBegin = response.border.Begin - SensorWidth / 2; Sensor0AtBorderWidth = SensorWidth; Sensor1AtBorderBegin = response.border.End - SensorWidth / 2; Sensor1AtBorderWidth = SensorWidth; }, this); } private void Apply() { if (!WdPassword.Authorize("BorderSearch")) return; borderSearch.Enable = Enable; borderSearch.IsOneMaterial = IsOneMaterial; borderSearch.IsBreakDetect = IsBreakDetect; borderSearch.Valid = Valid.ToStruct(); borderSearch.TempADBySet = TempADBySet; borderSearch.TempAD = TempAD; borderSearch.TempRange = TempRange; borderSearch.IsTempRangeByPercent = IsTempRangeByPercent; borderSearch.TempRangePercent = TempRangePercent; borderSearch.N = N; borderSearch.SensorWidth = SensorWidth; borderSearch.N2 = N2; borderSearch.N3 = N3; borderSearch.Apply(); string tit = (string)Application.Current.TryFindResource("str.PgBorderSearch.ApplySuccessfully"); FLY.ControlLibrary.Window_Tip.Show(tit,null,TimeSpan.FromSeconds(2)); } void UpdateRange() { List<double> vlist = new List<double>(); var value0s = Values.Where(v => !double.IsNaN(v.Y)).Select(v => v.Y); vlist.AddRange(value0s); if (vlist.Count() == 0) { //没有任何数据 return; } else { double max = vlist.Max(); double min = vlist.Min(); double range = max - min; if (range < 10) range = 10; ZoomInHelper.YRangeSlider.SliderMax = Math.Round(max + range / 10); ZoomInHelper.YRangeSlider.SliderMin = Math.Round(min - range / 10); } } int getPosFromGridIndex(int gridIndex) { return gridIndex * PosOfGrid; } int getGridIndexFromPos(int pos) { return pos / PosOfGrid; } } }