using EPLAN.Harness.API; using EPLAN.Harness.Common; using EPLAN.Harness.Core.Controls; using EPLAN.Harness.ProjectCore; using EPLAN.Harness.ProjectCore.Occurrences; using EPLAN.Harness.ProjectCore.Occurrences.Designer; using Sinvo.EplanHpD.Plugin.WPFUI.Models; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Windows.Threading; namespace Sinvo.EplanHpD.Plugin.WPFUI.ViewModel { public class ScannerViewModel : INotifyPropertyChanged, INotifyDataErrorInfo { private FlexDesigner _currentFlexDesigner; private bool _othersWireShow = true; private bool _continueScan = true; private bool _enableEvent = true; private bool _isIncludeAnnotation = true; private bool _scanAndAssembled = true; private int _scanedIndex = 1; public int ScanedIndex { get => _scanedIndex; set { _scanedIndex = value; OnPropertyChanged(nameof(ScanedIndex)); //WeakReferenceMessenger.Default.Send(new CommonMessage(value), "ScanedIndexChanged"); } } private string _inputCode; public string InputCode { get => _inputCode; set { if (_inputCode != value) { _inputCode = value; OnPropertyChanged(nameof(InputCode)); if (_enableEvent) { // 扫描输入框防抖,延迟一秒后触发 // 由于扫描枪不一定有发送回车事件,所以需要自动进行触发 if (_debounceTimer == null) { _debounceTimer = new DispatcherTimer(); _debounceTimer.Interval = TimeSpan.FromMilliseconds(1000); _debounceTimer.Tick += DebounceTimer_Tick; } _debounceTimer.Stop(); _debounceTimer.Start(); } } } } public ObservableCollection ScanCableModels { get; set; } = []; public ObservableCollection _ScanCableModels { get => ScanCableModels; set { if (ScanCableModels != value) { ScanCableModels = value; OnPropertyChanged(nameof(_ScanCableModels)); } } } #region private string _S_part; public string S_part { get => _S_part; set { _S_part = value; OnPropertyChanged(nameof(S_part)); } } private string _E_part; public string E_part { get => _E_part; set { _E_part = value; OnPropertyChanged(nameof(E_part)); } } private string _S_pin; public string S_pin { get => _S_pin; set { _S_pin = value; OnPropertyChanged(nameof(S_pin)); } } private string _E_pin; public string E_pin { get => _E_pin; set { _E_pin = value; OnPropertyChanged(nameof(E_pin)); } } private string _Name; public string Name { get => _Name; set { _Name = value; OnPropertyChanged(nameof(Name)); } } private string _Code; public string Code { get => _Code; set { _Code = value; OnPropertyChanged(nameof(Code)); } } private string _Length; public string Length { get => _Length; set { _Length = value; OnPropertyChanged(nameof(Length)); } } private string _Imprint; public string Imprint { get => _Imprint; set { _Imprint = value; OnPropertyChanged(nameof(Imprint)); } } #endregion private DispatcherTimer _debounceTimer; public ScannerViewModel() { } public void GetAllCables() { ScanCableModels.Clear(); string s_pinid = ""; string e_pinid = ""; _currentFlexDesigner.GetOrganizerOccurrences().ToList().ForEach(occ => { if (occ is OccWire wire) { if (wire.Name.StartsWith("w_", StringComparison.OrdinalIgnoreCase)) { //获取线两端管脚id,id唯一 var wire_pin = wire.DBG_GetPins.Split(';'); if (wire_pin.Length != 0) { s_pinid = wire_pin[0].Substring(1, 32); e_pinid = wire_pin[1].Trim().Substring(1, 32); } //保存线材基础属性 ScanCableModels.Add(new ScanCableModel() { Index = ScanCableModels.Count + 1, Id = wire.ID, S_Pin = wire.ConnectedPinsUI.Substring(0, wire.ConnectedPinsUI.IndexOf("<>")), E_Pin = wire.ConnectedPinsUI.Substring(wire.ConnectedPinsUI.IndexOf("<>") + 3, wire.ConnectedPinsUI.Length - wire.ConnectedPinsUI.IndexOf("<>") - 3), S_pinID = s_pinid, E_pinID = e_pinid, Name = wire.LibraryName, Length = Math.Ceiling(wire.Length_VH.GetValueInUnit(UNIT_CLASS.LENGTH)).ToString(), Code = wire.Name, Imprint = wire.Imprint }); } } }); } /// /// scaninfo界面数据 和找到管脚上级部件 /// /// public void GetWireConnectPart(ScanCableModel scanCableModel) { try { S_pin = scanCableModel.E_Pin; E_pin = scanCableModel.E_Pin; Length = scanCableModel.Length; Name = scanCableModel.Name; Code = scanCableModel.Code; Imprint = scanCableModel.Imprint; _currentFlexDesigner.GetOrganizerOccurrences().ToList().ForEach(occ => { //if (occ is OccConnector Assembly) //{ //var Assembly = occ; //根据管脚id获取上级部件信息 if (occ.ID.Equals(scanCableModel.S_pinID)) { var oriOcc = SelfControler.FindInstance(occ.ID); var parent = oriOcc.Parents?.FirstOrDefault(); var grandparent = parent.Parents?.FirstOrDefault(); scanCableModel.S_partObj = grandparent; scanCableModel.S_PartID = grandparent.ID; scanCableModel.S_part = grandparent.Name; S_part = scanCableModel.S_part; } if (occ.ID.Equals(scanCableModel.E_pinID)) { var oriOcc = SelfControler.FindInstance(occ.ID); var parent = oriOcc.Parents?.FirstOrDefault(); var grandparent = parent.Parents?.FirstOrDefault(); scanCableModel.E_partObj = grandparent; scanCableModel.E_PartID = grandparent.ID; scanCableModel.E_part = grandparent.Name; E_part = scanCableModel.E_part; } //} } ); } catch (Exception ex) { FlexMessageBox.Error(ex.Message); } } /// /// 获取当前设计器 /// public void GetCurrentDoc() { try { HpdApi api = HpdApi.GetInstance(); var currentDocId = api.CurrentProject.GetActiveDocument()?.ID; var designer = SelfControler.FindInstance(currentDocId) as FlexDesigner; if (designer != null) { _currentFlexDesigner = designer; } else { FlexMessageBox.Warning("未找到当前打开的工作区,请先打开工作区"); } } catch (Exception ex) { FlexMessageBox.Error(ex.Message); } } private void DebounceTimer_Tick(object sender, EventArgs e) { _debounceTimer.Stop(); string searchText = InputCode; PerformSearch(searchText); } /// /// 扫描条码(印记/名称) /// /// private void PerformSearch(string searchText) { // 清除错误信息 ClearErrors(nameof(InputCode)); var cable = ScanCableModels.FirstOrDefault(c => c.Code.Equals(searchText, StringComparison.OrdinalIgnoreCase) || c.Imprint.StartsWith(searchText, StringComparison.OrdinalIgnoreCase)); if (cable != null) { // 处理其他线是否隐藏 OthersOccShow(!OthersWireShow); if (_continueScan) { // 清空输入框 _enableEvent = false; InputCode = string.Empty; _enableEvent = true; } // 扫描即装配 if (ScanAndAssembled) { cable.IsChecked = true; _ScanCableModels.Remove(cable); _ScanCableModels.Insert(0, cable); } GetWireConnectPart(cable); ScanedIndex = 0;//Math.Max(cable.Index - 1, 0); ToSourceById(cable); } else { // 添加错误信息 AddError(nameof(InputCode), "该条码不存在于列表中"); } } //public void sethightlight() //{ // ClearHighlights(); // var selectedObjects = HarnessApp.Selection.GetSelectedObjects(); // foreach (var obj in selectedObjects) // { // obj.SetHighlight(true); // 高亮选中部件 // } //} //private void ClearHighlights() //{ // var allObjects = HarnessApp.GetAllObjects(); // foreach (var obj in allObjects) // { // obj.SetHighlight(false); // 清除高亮 // } //} private void ToSourceByName(string wireName) { var occWire = _currentFlexDesigner.GetOccurrenceByName(wireName, typeof(OccWire)); if (occWire != null) { occWire.SetVisibility(true, null); _currentFlexDesigner.SelectSet.Clear(); _currentFlexDesigner.SelectSet.Add(occWire); _currentFlexDesigner.FitToSelectSet(); _currentFlexDesigner.SelectSet.OnSelectionChanged(); //_currentFlexDesigner.Camera.GraphicControl._HighlightNode() /* List> nodeByEntity = this._occTreeView.GetNodeByEntity(baseOccurrence); if (nodeByEntity != null) { foreach (DatTreeNodeEx datTreeNodeEx in nodeByEntity) { if (!this._occTreeView.SelectedNodes.Contains(datTreeNodeEx)) { this._occTreeView.SelectedNodes.Add(datTreeNodeEx); } } } */ } } /// /// 将设计器聚焦到对应的线 /// /// public void ToSourceById(string occId) { // 从设计器中获取线实例 var occWire = _currentFlexDesigner.GetOccurrenceByID(occId); var scanedWire = ScanCableModels.FirstOrDefault(); if (occWire != null) { // 设置线显示 occWire.SetVisibility(true, null); // 清空已选择项并加入当前线 _currentFlexDesigner.SelectSet.Clear(); _currentFlexDesigner.SelectSet.Add(occWire); if (occId.Equals(scanedWire.S_PartID)|| occId.Equals(scanedWire.S_pinID) ) _currentFlexDesigner.SelectSet.Add(scanedWire.S_partObj.Children.Where(it => it.Type == OCC_TYPE.wPART)); else _currentFlexDesigner.SelectSet.Add(scanedWire.E_partObj.Children.Where(it => it.Type == OCC_TYPE.wPART)); // 缩放设计器且触发选中事件 _currentFlexDesigner.FitToSelectSet(); _currentFlexDesigner.SelectSet.OnSelectionChanged(); //_currentFlexDesigner.Camera.GraphicControl._HighlightNode() /* List> nodeByEntity = this._occTreeView.GetNodeByEntity(baseOccurrence); if (nodeByEntity != null) { foreach (DatTreeNodeEx datTreeNodeEx in nodeByEntity) { if (!this._occTreeView.SelectedNodes.Contains(datTreeNodeEx)) { this._occTreeView.SelectedNodes.Add(datTreeNodeEx); } } } */ } } /// /// 将设计器聚焦到对应的线 /// /// public void ToSourceById(ScanCableModel scanedWire) { var occId = scanedWire.Id; // 从设计器中获取线实例 var occWire = _currentFlexDesigner.GetOccurrenceByID(occId); if (occWire != null) { // 设置线显示 occWire.SetVisibility(true, null); // 清空已选择项并加入当前线 _currentFlexDesigner.SelectSet.Clear(); _currentFlexDesigner.SelectSet.Add(scanedWire.S_partObj.Children.Where(it => it.Type == OCC_TYPE.wPART)); _currentFlexDesigner.SelectSet.Add(scanedWire.E_partObj.Children.Where(it => it.Type == OCC_TYPE.wPART)); _currentFlexDesigner.SelectSet.Add(occWire); // 缩放设计器且触发选中事件 _currentFlexDesigner.FitToSelectSet(); _currentFlexDesigner.SelectSet.OnSelectionChanged(); //_currentFlexDesigner.Camera.GraphicControl._HighlightNode() /* List> nodeByEntity = this._occTreeView.GetNodeByEntity(baseOccurrence); if (nodeByEntity != null) { foreach (DatTreeNodeEx datTreeNodeEx in nodeByEntity) { if (!this._occTreeView.SelectedNodes.Contains(datTreeNodeEx)) { this._occTreeView.SelectedNodes.Add(datTreeNodeEx); } } } */ } } public void OthersOccShow(bool show = false) { // 获取设计器中所有的Occurrence _currentFlexDesigner.GetOrganizerOccurrences().ToList().ForEach(occ => { // 导线 if (occ is OccWire wire) { wire.SetVisibility(show, null); } // 电缆 if (occ is OccCableForked cable) { cable.SetVisibility(show, null); } // 是否包含注解 if (_isIncludeAnnotation) { // 注解 if (occ is OccAnnotation annotation) { Debug.WriteLine($"BaseOccurrence -> {annotation.Name} Type: {annotation.GetType().Name}"); annotation.SetVisibility(show, null); } } }); if (show) { // 放大到选中的线 _currentFlexDesigner.FitToSelectSet(); } } // 添加属性以绑定界面上的控件,例如复选框等 public bool OthersWireShow { get => _othersWireShow; set { if (_othersWireShow != value) { _othersWireShow = value; OnPropertyChanged(nameof(OthersWireShow)); } } } public bool ContinueScan { get => _continueScan; set { if (_continueScan != value) { _continueScan = value; OnPropertyChanged(nameof(ContinueScan)); } } } public bool IsIncludeAnnotation { get => _isIncludeAnnotation; set { if (_isIncludeAnnotation != value) { _isIncludeAnnotation = value; OnPropertyChanged(nameof(IsIncludeAnnotation)); } } } public bool ScanAndAssembled { get => _scanAndAssembled; set { if (_scanAndAssembled != value) { _scanAndAssembled = value; OnPropertyChanged(nameof(ScanAndAssembled)); } } } public void ExportWires(string path) { MiniExcelLibs.MiniExcel.SaveAs(path, ScanCableModels.Select(it => new { 序号 = it.Index, 导线名称 = it.Code, 导线型号 = it.Name, 导线是否已扫描 = it.IsChecked ? "是" : "否" })); } #region Notify // 实现 INotifyPropertyChanged 接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 实现 INotifyDataErrorInfo 接口 private readonly Dictionary> _errors = new Dictionary>(); public bool HasErrors => _errors.Any(); public event EventHandler ErrorsChanged; public IEnumerable GetErrors(string propertyName) { if (string.IsNullOrEmpty(propertyName)) return null; _errors.TryGetValue(propertyName, out var errorsForName); return errorsForName; } protected void OnErrorsChanged(string propertyName) { ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); } private void AddError(string propertyName, string error) { if (!_errors.ContainsKey(propertyName)) { _errors[propertyName] = new List(); } if (!_errors[propertyName].Contains(error)) { _errors[propertyName].Add(error); OnErrorsChanged(propertyName); } } private void ClearErrors(string propertyName) { if (_errors.ContainsKey(propertyName)) { _errors.Remove(propertyName); OnErrorsChanged(propertyName); } } #endregion } }