using System; using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel.Params; using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using DataGridRowEventArgs = ExtendedGrid.Microsoft.Windows.Controls.DataGridRowEventArgs; using ExDataGridRow = ExtendedGrid.Microsoft.Windows.Controls.DataGridRow; using MECF.Framework.UI.Client.RecipeEditorLib.DGExtension.CustomColumn; using System.Diagnostics; using DataGridCellEditEndingEventArgs = ExtendedGrid.Microsoft.Windows.Controls.DataGridCellEditEndingEventArgs; using MECF.Framework.UI.Client.ClientBase; using OpenSEMI.ClientBase; using DataGridBeginningEditEventArgs = ExtendedGrid.Microsoft.Windows.Controls.DataGridBeginningEditEventArgs; namespace MECF.Framework.UI.Client.RecipeEditorLib.DGExtension { /// /// Interaction logic for DataGridRecipe.xaml /// public partial class DataGridRecipe : UserControl { #region Constructors public DataGridRecipe() { InitializeComponent(); } #endregion #region Properties #endregion #region Dependency Properties public static readonly DependencyProperty AllowDragToFillProperty = DependencyProperty.Register( nameof(AllowDragToFill), typeof(bool), typeof(DataGridRecipe), new PropertyMetadata(true)); public bool AllowDragToFill { get => (bool)GetValue(AllowDragToFillProperty); set => SetValue(AllowDragToFillProperty, value); } #region RecipeData public static readonly DependencyProperty RecipeProperty = DependencyProperty.Register( nameof(Recipe), typeof(RecipeData), typeof(DataGridRecipe), new PropertyMetadata(default(RecipeData), RecipePropertyChangedCallback)); private static void RecipePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is DataGridRecipe dg) { if (e.NewValue is RecipeData recipe) { dg.dgCustom.ItemsSource = recipe.Steps; recipe.PropertyChanged += (sender, e) => { // 同步白名单编辑模式 if (e.PropertyName == nameof(RecipeData.IsAccessibleWhitelistEditMode)) { dg.dgCustom.IsAccessibleWhitelistEditMode = recipe.IsAccessibleWhitelistEditMode; } }; // 创建DataGrid列 dg.ClearColumns(); foreach (var col in recipe.Columns) dg.AddColumn(col); } else dg.dgCustom.ItemsSource = null; } } /// /// 设置或返回编辑器正在编辑的Recipe。 /// public RecipeData Recipe { get => (RecipeData)GetValue(RecipeProperty); set => SetValue(RecipeProperty, value); } #endregion #region FrozenColumnCount public static readonly DependencyProperty FrozenColumnCountProperty = DependencyProperty.Register( nameof(FrozenColumnCount), typeof(int), typeof(DataGridRecipe), new PropertyMetadata(default(int), FrozenColumnCountPropertyChangedCallback)); private static void FrozenColumnCountPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is DataGridRecipe dg) { if (e.NewValue is int count) dg.dgCustom.FrozenColumnCount = count; else dg.dgCustom.FrozenColumnCount = 0; } } /// /// 设置或返回编辑器冻结的列数。 /// public int FrozenColumnCount { get => (int)GetValue(FrozenColumnCountProperty); set => SetValue(FrozenColumnCountProperty, value); } #endregion #endregion #region Methods private void RowOnSelected(object sender, RoutedEventArgs e) { if (!(e.Source is ExDataGridRow dgr)) return; if (!(dgr.DataContext is RecipeStep recipeStep)) return; var param = recipeStep.FindParamByControlName(RecipeControlNames.STEP_NO); if (param is StepParam sp) { sp.IsChecked = true; } } private void RowOnUnselected(object sender, RoutedEventArgs e) { if (!(e.Source is ExDataGridRow dgr)) return; if (!(dgr.DataContext is RecipeStep recipeStep)) return; var param = recipeStep.FindParamByControlName(RecipeControlNames.STEP_NO); if (param is StepParam sp) { sp.IsChecked = false; } } private void ClearColumns() { dgCustom.Columns.Clear(); } /// /// 生成编辑器的列。 /// private void AddColumn(EditorDataGridTemplateColumnBase col) { // 设置ColumnHeaderTemplate和DataGridCellTemplate if (string.IsNullOrEmpty(col.StringCellTemplate) == false) col.CellTemplate = (DataTemplate)FindResource(col.StringCellTemplate); if (string.IsNullOrEmpty(col.StringCellEditingTemplate) == false) col.CellEditingTemplate = (DataTemplate)FindResource(col.StringCellEditingTemplate); if (string.IsNullOrEmpty(col.StringHeaderTemplate) == false) col.HeaderTemplate = (DataTemplate)FindResource(col.StringHeaderTemplate); // 通过Columns重建XDataGrid列 dgCustom.Columns.Add(col); } /// /// 滚动到并高亮指定的参数单元格。 /// /// public void FocusToParam(IParam param) { if (param == null) return; Recipe.Steps.ResetHighlight(); var row = param.RowOwner; var col = param.ColumnOwner; if (row != null && col != null) { dgCustom.ScrollIntoView(param.Parent, col); param.Highlight(); } } #endregion #region Events private void DgCustom_OnBeginningEdit(object sender, DataGridBeginningEditEventArgs e) { Debug.Assert(e.Row.Item is RecipeStep, "The content of row is not RecipeStep."); if (e.Row.Item is RecipeStep step) { var param = step[e.Column.DisplayIndex]; if (param is IValueParam && param.Permission != MenuPermissionEnum.MP_READ_WRITE) { e.Cancel = true; // 如果单元格为只读权限,则提示不能编辑 var reason = ""; if (param.ColumnPermission != MenuPermissionEnum.MP_READ_WRITE) reason = "Recipe Row Access Denied!\r\n\r\nPlease check the RecipeRow Access Permission."; else if (param.StepPermission != MenuPermissionEnum.MP_READ_WRITE) reason = "Recipe Step Access Denied!\r\n\r\nPlease check the RecipeCol Access Permission."; else reason = "Cell Access Denied!\r\n\r\nPlease check the RecipeRow/RecipeCol Access Permission."; DialogBox.ShowError(reason); } } else e.Cancel = true; } private void DataGridCell_OnPreviewMouseDown(object sender, MouseButtonEventArgs e) { // 仅在编辑AccessPermissionWhitelist编辑模式下有效。 if (!Recipe.IsAccessibleWhitelistEditMode) return; if (sender is Border bdr && bdr.DataContext is Param param) { if (param.IsHighlighted) param.ResetHighlight(); else param.Highlight(); } } private void DgCustom_OnLoadingRow(object sender, DataGridRowEventArgs e) { e.Row.Selected += RowOnSelected; e.Row.Unselected += RowOnUnselected; if (sender is XDataGrid dg && e.Row.DataContext is RecipeStep step) { for (var i = 0; i < step.Count; i++) { step[i].RowOwner = e.Row; step[i].ColumnOwner = dg.Columns[i]; } } } private void DgCustom_OnUnloadingRow(object sender, DataGridRowEventArgs e) { e.Row.Selected -= RowOnSelected; e.Row.Unselected -= RowOnUnselected; } private void DgCustom_OnCellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { if (e.Row.Item is RecipeStep step) { step.CalculateGasFlow(); step.Parent.Validate(); } } private void Expander_OnExpanded(object sender, RoutedEventArgs e) { if (sender is Expander expander && expander.DataContext is ExpanderColumn col) { foreach (var subCol in col.ChildColumns) { subCol.UpdateVisibility(); } } } private void Expander_OnCollapsed(object sender, RoutedEventArgs e) { if (sender is Expander expander && expander.DataContext is ExpanderColumn col) { foreach (var subCol in col.ChildColumns) { subCol.Visibility = Visibility.Collapsed; } } } /// /// 滚动DataGrid视图到指定的配方步骤。 /// /// public void ScrollToRecipeStep(RecipeStep step) { dgCustom.ScrollIntoView(step); } #endregion } }