using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using SciChart.Core.Extensions; namespace RecipeEditorLib.RecipeModel.Params { public class RecipeStep : ObservableCollection { /// /// 步骤起始编号。 /// public const int START_INDEX = 1; #region Variables private bool _isHideValue; /// /// 当配方步骤的IsSaved属性发生变化时,触发此事件。 /// public event EventHandler SavedStateChanged; #endregion #region Constructors public RecipeStep(RecipeStep previous) { Previous = previous; IsSaved = true; } #endregion #region Properties /// /// 父级配方集合。 /// public RecipeStepCollection Parent { get; internal set; } /// /// 返回配方步骤序号参数。 /// public StepParam StepNoParam => this.FirstOrDefault(x => x is StepParam) as StepParam; /// /// 返回步骤序号。 /// public int? StepNo { get { var param = StepNoParam; return param?.Value ?? null; } } /// /// 返回步骤执行时长。 /// public double? StepTime { get { var param = this.FirstOrDefault(x => x is DoubleParam && string.Equals(x.Name, RecipColNo.Time.ToString(), StringComparison.CurrentCultureIgnoreCase)) as DoubleParam; return param?.Value; } } /// /// 返回当前配方步骤是否已保存。 /// public bool IsSaved { get; private set;} /// /// 返回前序配方。 /// public RecipeStep Previous { get; private set; } /// /// 返回后序配方。 /// public RecipeStep Next { get; private set;} /// /// 返回是否隐藏当前步骤的参数值。 /// public bool IsHideValue { get => _isHideValue; set { _isHideValue = value; this.ToList().ForEach(x => x.IsHideValue = value); } } #endregion #region Methods /// /// 当配方中的参数的属性发生变化时,触发此事件。 /// /// /// private void ParamOnPropertyChanged(object sender, PropertyChangedEventArgs e) { if (!(sender is IParam param)) return; if (e.PropertyName == nameof(Param.IsSaved)) { if (param.IsSaved == false) { IsSaved = false; } else { IsSaved = this.ToList().FirstOrDefault(x => x.IsSaved == false) == null; } SavedStateChanged?.Invoke(this, IsSaved); } } /// /// 将指定的Param链接到前序Param。 /// /// 当前Step中的参数。 private void LinkWithPreviousParam(IParam param) { var preParam = Previous?.FirstOrDefault(x => x.Name == param.Name); param.Previous = preParam; if (preParam != null) preParam.Next = param; } /// /// 将指定的Param链接到后序Param。 /// /// 当前Step中的参数。 private void LinkWithNextParam(IParam param) { var nextParam = Next?.FirstOrDefault(x => x.Name == param.Name); param.Next = nextParam; if (nextParam != null) nextParam.Previous = param; } /// /// 校验步骤中的所有参数。 /// public void Validate() { this.ToList().ForEach(x=>x.Validate()); } /// /// 取消所有参数的Highlight状态。 /// public void ResetHighlight() { this.ToList().ForEach(x => x.ResetHighlight()); } /// /// 保存当前配方步骤。 /// public void Save() { this.ToList().ForEach(x=>x.Save()); } /// /// 設置前序步驟。 /// /// public void SetPreviousStep(RecipeStep step) { Previous = step; // 调整Step中Param的链接关系 this.ToList().ForEach(LinkWithPreviousParam); if (Previous == null) return; // 将前序步骤的后序步骤链接到我自己。 Previous.Next = this; } public void SetNextStep(RecipeStep step) { Next = step; this.ToList().ForEach(LinkWithNextParam); } /// /// 检查StepNo是否为有效值。 /// /// /// /// public static bool ValidateStepNo(int? stepNo, out int validatedStepNo) { validatedStepNo = int.MinValue; var isValid = stepNo >= START_INDEX; if (isValid) validatedStepNo = stepNo.Value; return isValid; } #endregion #region Override Methods protected override void InsertItem(int index, Param item) { if (item != null) { item.Parent = this; LinkWithPreviousParam(item); LinkWithNextParam(item); item.PropertyChanged += ParamOnPropertyChanged; } base.InsertItem(index, item); } protected override void SetItem(int index, Param item) { throw new NotSupportedException(); } protected override void RemoveItem(int index) { if (Count > 0) { if (index >= 0 && index < Count) { this[index].PropertyChanged -= ParamOnPropertyChanged; } } // 将前后两个Param链接起来 var preParam = this[index].Previous; var nextParam = this[index].Next; if (preParam != null && nextParam != null) { preParam.Next = nextParam; nextParam.Previous = preParam; } else if (preParam == null && nextParam != null) { nextParam.Previous = null; } else if (preParam != null) { preParam.Next = null; } IsSaved = false; SavedStateChanged?.Invoke(this, true); base.RemoveItem(index); } protected override void ClearItems() { this.ToList().ForEach(x => x.PropertyChanged -= ParamOnPropertyChanged); IsSaved = Count <= 0; SavedStateChanged?.Invoke(this, true); base.ClearItems(); } public override string ToString() { return Count > 0 ? (StepNoParam.ToString()??"Recipe Step, Item={Count}" ): "Empty Recipe Step"; } #endregion } }