Imports System.Diagnostics.Eventing.Reader Imports System.Drawing Imports System.Windows.Forms Imports FlexCell Imports FluentFTP Imports UTS_Core.UTSModule.Production Imports UTS_Core.UTSModule.Test.Command Imports UTS_Core.UTSModule.Test.StatusMonitor Namespace UTSModule.Station Public Class StationPlanGrid ''' 表格控件对象 Private _grd As Grid ''' 表格树状目录起始节点 Private _headNode As RowNode ''' 起始绘制列 Private _drawCol As Integer ''' 起始绘制行 Private _drawStartRow As Integer ''' 调试模式是否开启 Private _debugMode As Boolean ''' 是否显示节点图标 Private ReadOnly _showNodeIcon As Boolean ''' 处于更新表格状态中,不触发表格单元格修改事件 Private _uploading As Boolean ''' 多个参数间的分割符号 Private ReadOnly _paramChar As Char ''' 测试命令管理器 Private ReadOnly _testCmdManager As TestCmdManager ''' 错误代码管理器 Private ReadOnly _errCodeManager As ErrCodeManager ''' 表格标签字段字典 Private ReadOnly _labelNames As New Dictionary(Of String, Integer) ''' 表格记录名称字段字典 Private ReadOnly _recordNames As New Dictionary(Of String, Integer) Private gMouseOldRow As Integer '记录鼠标移动前的行号 Private gMouseOldCol As Integer Private gOldRowType As Integer Private gRowType As Integer Private gDescTextColor As Brush 'description cell 文字颜色 Private gIsGri_MouseMove_EventReady As Boolean = True 'MoveMove 函数加锁,防止嵌套执行 ''' 当前活动节点 Public ActiveNode As RowNode ''' 节点选择改变事件 Public Event PlanNodeSelectChanged(ByVal sender As Object, ByVal e As PlanNodeSelectChangedEventArgs) ''' 节点文本被修改事件 Public Event RowNodeTextChanged(ByVal sender As Object, ByVal e As RowNodeChangedEventArgs) ''' 节点执行可撤销事件 Public Event PlanGridCommandChanged(ByVal sender As Object, ByVal e As EventArgs) ''' 粘贴操作计时器 Private WithEvents _userActionTimer As New Timer() ''' 计时器超时时间 Private Const UserActionTimeout As Integer = 300 ' ms Private _dicTextChangedRowNode As New Dictionary(Of Integer, TextChangedRowNode) '记录文本修改的行号和节点对象 ''' ''' 构造函数 ''' Sub New() NodeStartRow = 1 _drawCol = ColNames.Description _showNodeIcon = False _uploading = False _paramChar = "#"c _testCmdManager = TestCmdManager.CreateManager() _errCodeManager = ErrCodeManager.CreateManager() _userActionTimer.Interval = UserActionTimeout _userActionTimer.Stop() End Sub ''' ''' 表格内容改变处理事件 ''' Private Sub OnUserAction(node As RowNode) If CommandManager.IsRuning Then Return ' 每次用户操作都重置计时器 _userActionTimer.Stop() _userActionTimer.Start() '记录当前活动节点 If Not _dicTextChangedRowNode.ContainsKey(node.RowListIndex) Then _dicTextChangedRowNode.Add(node.RowListIndex, New TextChangedRowNode With {.BeforeRowNode = node.Clone}) End If End Sub Private Sub OnUserActionEnd(node As RowNode) If CommandManager.IsRuning Then Return '记录当前活动节点 If _dicTextChangedRowNode.ContainsKey(node.RowListIndex) Then _dicTextChangedRowNode(node.RowListIndex).AfterRowNode = node.Clone End If End Sub ''' ''' 粘贴操作计时器超时处理事件 ''' ''' ''' Private Sub _userActionTimer_Tick(sender As Object, e As EventArgs) Handles _userActionTimer.Tick _userActionTimer.Stop() OnUserActionTimeout() End Sub Private Sub OnUserActionTimeout() If CommandManager.IsRuning = False Then CommandManager.AddUndoCommand(New GridNodeTextChangedCommand(Me, _dicTextChangedRowNode)) RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End If _dicTextChangedRowNode = New Dictionary(Of Integer, TextChangedRowNode) End Sub ''' ''' 屏蔽表格引发自定义事件,避免行节点内容修改,todo:暂未完成 ''' ''' Public Property SkipEvent() As Boolean Property DebugMode() As Boolean Get Return _debugMode End Get Set(value As Boolean) _debugMode = value UpdateColVisible() End Set End Property Property Grid() As Grid Get Return _grd End Get Set(value As Grid) _grd = value InitializeGrid() 'RemoveHandler _grd.Click, AddressOf Grid_Click RemoveHandler _grd.CellChange, AddressOf Grid_CellChange RemoveHandler _grd.SelChange, AddressOf Grid_SelChange RemoveHandler _grd.LeaveCell, AddressOf Grid_LeaveCell RemoveHandler _grd.ComboDropDown, AddressOf Grid_ComboDropDown RemoveHandler _grd.ComboClick, AddressOf Grid_ComboClick RemoveHandler _grd.MouseMove, AddressOf Grid_MouseMove RemoveHandler _grd.MouseLeave, AddressOf Grid_MouseLeave RemoveHandler _grd.MouseEnter, AddressOf Grid_MouseEnter 'AddHandler _grd.Click, AddressOf Grid_Click AddHandler _grd.CellChange, AddressOf Grid_CellChange AddHandler _grd.SelChange, AddressOf Grid_SelChange AddHandler _grd.LeaveCell, AddressOf Grid_LeaveCell AddHandler _grd.ComboDropDown, AddressOf Grid_ComboDropDown AddHandler _grd.ComboClick, AddressOf Grid_ComboClick AddHandler _grd.MouseMove, AddressOf Grid_MouseMove AddHandler _grd.MouseLeave, AddressOf Grid_MouseLeave AddHandler _grd.MouseEnter, AddressOf Grid_MouseEnter _grd.ComboBox(ColNames.CommandType).Items.Clear() _grd.ComboBox(ColNames.CommandType).Items.AddRange(_testCmdManager.GetCommandTypes()) _grd.ComboBox(ColNames.ErrorCode).Items.Clear() _grd.ComboBox(ColNames.ErrorCode).Items.AddRange(_errCodeManager.GetAllCodeAndMsg()) End Set End Property Private _autoRedraw As Integer = 0 Private Sub LockGridAutoRedraw() If _autoRedraw = 0 Then _grd.AutoRedraw = False _autoRedraw += 1 End Sub Private Sub UnLockGridAutoRedraw() _autoRedraw -= 1 If _autoRedraw = 0 Then _grd.AutoRedraw = True _grd.Refresh() End If End Sub #Region "导航功能" ''' ''' 向后导航 ''' Public Sub BackwardNavigation() GridNavigationManager.Backward() End Sub ''' ''' 向前导航 ''' Public Sub ForwardNavigation() GridNavigationManager.Forward() End Sub ''' ''' 是否可以后退 ''' ''' ''' Public Function CanBackward() As Boolean Return GridNavigationManager.CanBackward End Function ''' ''' 是否可以前进 ''' ''' ''' Public Function CanForward() As Boolean Return GridNavigationManager.CanForward End Function ''' ''' ''' Public Sub ClearNavigation() GridNavigationManager.Clear() _lastSelction = Nothing _lastTempSelction = Nothing End Sub Public Sub JumpCall() If _grd.ActiveCell Is Nothing Then Return Dim row As Integer = _grd.ActiveCell.Row Dim node As RowNode = _headNode.RowList(row - _drawStartRow + 1) If node.CommandType = "System" AndAlso node.Command = "Call" Then Dim labelName As String = node.Parameters(0).Value If String.IsNullOrWhiteSpace(labelName) Then MsgBox("请填写有效的模块名!") Else If IsExistLabelName(labelName) Then Dim destRow As Integer = GetLabelNameGridRow(labelName) _grd.Cell(destRow, ColNames.Label).SetFocus() Else MsgBox($"未发现当前模块名[{labelName}]匹配的模块!") End If End If End If End Sub #End Region #Region "撤销功能" Public Sub ClearCommand() CommandManager.ClearCommands() RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Public Function CanUndo() As Boolean Return CommandManager.CanUndo End Function Public Function CanRedo() As Boolean Return CommandManager.CanRedo End Function Public Sub UndoCommand() If CommandManager.CanUndo Then CommandManager.Undo() RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End If End Sub Public Sub RedoCommand() If CommandManager.CanRedo Then CommandManager.Redo() RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End If End Sub #End Region #Region "字段去重" ''' ''' 当前模块名是否已存在 ''' ''' ''' Public Function IsExistLabelName(labelName As String) As Boolean labelName = labelName.ToLower() Return _labelNames.ContainsKey(labelName) End Function ''' ''' 当前字段名 ''' ''' ''' Public Function IsExistRecordName(recordName As String) As Boolean recordName = recordName.ToLower() Return _recordNames.ContainsKey(recordName) End Function ''' ''' 清空标签名称 ''' Private Sub ClearLabelNames() _labelNames.Clear() End Sub ''' ''' 清空记录名称 ''' Private Sub ClearRecordNames() _recordNames.Clear() End Sub ''' ''' 添加标签名称 ''' ''' 标签名称 ''' 行号 Private Sub AddLabelName(labelName As String, row As Integer) labelName = labelName.ToLower() If Not _labelNames.ContainsKey(labelName) Then _labelNames.Add(labelName, row) End If End Sub ''' ''' 添加记录名称 ''' ''' 记录名 ''' 行号 Private Sub AddRecordName(recordName As String, row As Integer) recordName = recordName.ToLower() If Not _recordNames.ContainsKey(recordName) Then _recordNames.Add(recordName, row) End If End Sub ''' ''' 移出标签名称 ''' ''' 标签名称 Private Sub RemoveLabelName(labelName As String) labelName = labelName.ToLower() If _labelNames.ContainsKey(labelName) Then _labelNames.Remove(labelName) End If End Sub ''' ''' 移出记录名称 ''' ''' 记录名称 Private Sub RemoveRecordName(recordName As String) recordName = recordName.ToLower() If _recordNames.ContainsKey(recordName) Then _recordNames.Remove(recordName) End If End Sub ''' ''' 获取标签名称行号 ''' ''' ''' Private Function GetLabelNameGridRow(labelName As String) As Integer labelName = labelName.ToLower() Return _labelNames(labelName) End Function ''' ''' 获取记录名称行号 ''' ''' ''' Private Function GetRecordNameGridRow(recordName As String) As Integer recordName = recordName.ToLower() Return _recordNames(recordName) End Function ''' ''' 从表格中重载标签名称 ''' Private Sub ReflushLabelNames() ClearLabelNames() If _headNode Is Nothing Then Return For Each node As RowNode In _headNode.RowList If node.RowType = RowNode.RowTypeEnum.Module OrElse node.RowType = RowNode.RowTypeEnum.FixedModule Then If Not String.IsNullOrWhiteSpace(node.Label) AndAlso Not IsExistLabelName(node.Label) Then AddLabelName(node.Label, node.RowListIndex) End If End If Next End Sub ''' ''' 从表格中重载记录名称 ''' Private Sub ReflushRecordNames() ClearRecordNames() If _headNode Is Nothing Then Return For Each node As RowNode In _headNode.RowList If Not String.IsNullOrWhiteSpace(node.RecordName) AndAlso Not IsExistRecordName(node.RecordName) Then AddRecordName(node.RecordName, node.RowListIndex) End If Next End Sub #End Region '离开表格时活动单元格背景颜色 Private leaveColor As Color = Color.White '离开表格时活动单元格行号 Private leaveRow As Integer = 0 ''' ''' 光标离开grd表格时,黄色底色切换到选中行 ''' Public Sub Grid_MouseLeave(sender As Object, e As EventArgs) If _grd.EditorVisible Then Return '处于编辑状态 If _grd.ActiveCell.Row <= 0 Then Return leaveRow = _grd.ActiveCell.Row leaveColor = _grd.ActiveCell.BackColor _grd.Range(leaveRow, ColNames.Result, leaveRow, ColNames.ErrorMessage).BackColor = Color.LightCyan End Sub ''' ''' 光标进入grd表格时,原底色切换到选中行 ''' Public Sub Grid_MouseEnter(sender As Object, e As EventArgs) If _grd.EditorVisible Then Return '处于编辑状态 If leaveRow <= 0 Then Return Try _grd.Range(leaveRow, ColNames.Result, leaveRow, ColNames.ErrorMessage).BackColor = leaveColor Catch ex As Exception End Try End Sub ''' ''' 鼠标移动到节点位置时所有子节点背景着色 ''' Private Sub Mouse_MoveOnNode_BackColorRepain(grd As Grid, rowType As Integer, startRowIdx As Integer, backColor As Color) '起始行NodeLevel Dim startRowNodeLevel As Integer = GetRowNodeLevel(grd, startRowIdx) '结束行号 Dim endRowNodeIdx As Integer '当前行行号和node level Dim tmpCurrRowIdx As Integer = startRowIdx Dim tmpCurrRowNodeLevel As Integer = GetRowNodeLevel(grd, tmpCurrRowIdx) '判断当前行Row type = 1,记录下本行的NodeLevel = tempNodeLevel,记录NodeLstIndx If rowType = RowNode.RowTypeEnum.Module Then '从起始行开始往下遍历 Do If tmpCurrRowIdx < Grid.Rows Then '遍历到最大行还未结束 tmpCurrRowIdx = tmpCurrRowIdx + 1 tmpCurrRowNodeLevel = GetRowNodeLevel(grd, tmpCurrRowIdx) Else Return End If Loop Until tmpCurrRowNodeLevel <= startRowNodeLevel Or tmpCurrRowIdx >= Grid.Rows '再次遍历到与起始行同级或更高级别的行,就算是该节点遍历结束 endRowNodeIdx = tmpCurrRowIdx - 1 '底色着色 LockGridAutoRedraw() grd.Range(startRowIdx, ColNames.Result, endRowNodeIdx, ColNames.ErrorMessage).BackColor = backColor UnLockGridAutoRedraw() End If End Sub Private Function GetRowNodeAction(node As RowNode) As Boolean If node.ParentNode.RowLever <= 1 Then Return node.ParentNode.Action Else If node.ParentNode.Action Then Return GetRowNodeAction(node.ParentNode) Else Return False End If End If End Function Private Function GetRowNodeForeColor(node As RowNode) As Color If node.Action Then If node.RowLever > 1 AndAlso GetRowNodeAction(node) = False Then Return Color.LightGray Select Case node.RowType Case RowNode.RowTypeEnum.Flow Select Case node.CommandType Case "System" If node.Command = "Call" Then Return Color.Blue Else Return Color.DarkSlateGray End If Case "ComPort" Return Color.Olive Case "UtsComPort" Return Color.SeaGreen Case "Converter" Return Color.DarkOrange Case "Process" Return Color.DarkBlue Case Else Return Color.Black End Select Case RowNode.RowTypeEnum.Module Return Color.DeepPink Case RowNode.RowTypeEnum.FixedModule Return Color.Blue Case Else Return Color.Black End Select Else Return Color.LightGray End If End Function ''' ''' 节点类型变更,修改节点行样式 ''' ''' Private Sub NodeRowTypeChanged(node As RowNode) Dim row As Integer = node.RowListIndex With _grd If node.RowType = RowNode.RowTypeEnum.FixedModule Then .Cell(row, ColNames.Label).FontSize = 10 .Cell(row, ColNames.Label).FontBold = True ElseIf node.RowType = RowNode.RowTypeEnum.Module Then .Cell(row, ColNames.Label).FontSize = 8 .Cell(row, ColNames.Label).FontBold = True ElseIf node.RowType = RowNode.RowTypeEnum.Flow Then .Cell(row, ColNames.Label).FontSize = 8 .Cell(row, ColNames.Label).FontBold = False End If NodeActionChanged(node) End With End Sub ''' ''' 节点状态变更,修改节点行颜色 ''' ''' Private Sub NodeActionChanged(node As RowNode) Dim row As Integer = node.RowListIndex Dim tmpRowColor As Color LockGridAutoRedraw() tmpRowColor = GetRowNodeForeColor(node) '获取选颜色 _grd.Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = tmpRowColor '着色 If node.SaveToDb = False Then _grd.Cell(row, ColNames.RecordName).ForeColor = Color.LightGray '着色 End If If node.CommandType = "" And node.Description = "" Then '空白行字体与底色同色,避免对编辑产生干扰 _grd.Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = _grd.Cell(row, ColNames.Description).BackColor '着色 End If If node.RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Range(row, ColNames.CommandType, row, ColNames.ErrorMessage).ForeColor = _grd.Cell(row, ColNames.Description).BackColor '着色 End If For i As Integer = 0 To node.RowNodes.Count - 1 NodeActionChanged(CType(node.RowNodes(i), RowNode), node.Action) Next UnLockGridAutoRedraw() End Sub ''' ''' 节点状态变更,修改节点行颜色 ''' ''' Private Sub NodeActionChanged(node As RowNode, action As Boolean) Dim row As Integer = node.RowListIndex Dim tmpRowColor As Color tmpRowColor = GetRowNodeForeColor(node) '获取选颜色 _grd.Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = tmpRowColor '着色 If node.SaveToDb = False Then _grd.Cell(row, ColNames.RecordName).ForeColor = Color.LightGray '着色 End If If node.CommandType = "" And node.Description = "" Then '空白行字体与底色同色,避免对编辑产生干扰 _grd.Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = _grd.Cell(row, ColNames.Description).BackColor '着色 End If If node.RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Range(row, ColNames.CommandType, row, ColNames.ErrorMessage).ForeColor = _grd.Cell(row, ColNames.Description).BackColor '着色 End If For i As Integer = 0 To node.RowNodes.Count - 1 NodeActionChanged(CType(node.RowNodes(i), RowNode), action) Next End Sub ''' ''' 选定行使能或清除Action选项 ''' Public Sub Check_Uncheck_Action(grd As Grid, startRow As Integer, endRow As Integer, IsCheck As Boolean) Dim idx As Integer If endRow < startRow Then Return For idx = startRow To endRow grd.Cell(idx, ColNames.Action).Text = IsCheck.ToString Next End Sub ''' ''' 光标移动时,所在行底色高亮 ''' Private Sub Grid_MouseMove(Sender As Object, e As MouseEventArgs) If _grd.EditorVisible Then Return '处于编辑状态 If gIsGri_MouseMove_EventReady = True Then Dim tmpMouseRow As Integer = _grd.MouseRow '鼠标当前行’ Dim tmpMouseCol As Integer = _grd.MouseCol '鼠标当前列’ If tmpMouseRow <= 0 Or tmpMouseCol <= 0 Then Return Dim tmpMouseRowNodeIdx As Integer = GetRowNodeIdx(_grd, tmpMouseRow) '同级节点计数’ Dim tmpMouseRowNodeLevel As Integer = GetRowNodeLevel(_grd, tmpMouseRow) '节点级数 Dim tmpMouseRowNodeLstIdx As Integer = GetRowNodeLstIdx(_grd, tmpMouseRow) '就是行号 gRowType = GetRowType(_grd, tmpMouseRow) '现在所在行的row type gOldRowType = GetRowType(_grd, gMouseOldRow) '前一次的row type Try If tmpMouseRow <> gMouseOldRow Or tmpMouseCol <> gMouseOldCol Then '鼠标所在行变化 If gOldRowType <> RowNode.RowTypeEnum.FixedModule Then '光标离开Flow节点 _grd.Range(gMouseOldRow, ColNames.Result, gMouseOldRow, ColNames.ErrorMessage).BackColor = Color.White _grd.Cell(gMouseOldRow, gMouseOldCol).FontBold = False If gOldRowType = RowNode.RowTypeEnum.Module Then '光标离开Module节点 Mouse_MoveOnNode_BackColorRepain(_grd, gOldRowType, gMouseOldRow, Color.White) End If End If gMouseOldRow = tmpMouseRow gMouseOldCol = tmpMouseCol Else If gRowType <> RowNode.RowTypeEnum.FixedModule Then '光标移动到flow节点 _grd.Range(tmpMouseRow, ColNames.Result, tmpMouseRow, ColNames.ErrorMessage).BackColor = Color.LemonChiffon _grd.Cell(tmpMouseRow, tmpMouseCol).FontBold = True If gRowType = RowNode.RowTypeEnum.Module Then '光标移动到module节点 Mouse_MoveOnNode_BackColorRepain(_grd, gRowType, tmpMouseRow, Color.LemonChiffon) End If End If End If Catch ex As Exception gIsGri_MouseMove_EventReady = True End Try End If gIsGri_MouseMove_EventReady = True End Sub ''' ''' 获取指定行的NodeIndex ''' ''' Public Function GetRowNodeLstIdx(grd As Grid, cellRow As Integer) As Integer Try Dim node As RowNode = _headNode.RowList(cellRow - _drawStartRow + 1) Return node.RowListIndex Catch ex As Exception Return 0 End Try End Function ''' ''' 获取指定行的NodeLever ''' ''' Public Function GetRowNodeLevel(grd As Grid, cellRow As Integer) As Integer Try Dim node As RowNode = _headNode.RowList(cellRow - _drawStartRow + 1) Return node.RowLever Catch ex As Exception Return 0 End Try End Function ''' ''' 获取指定行的NodeIndex ''' ''' Public Function GetRowNodeIdx(grd As Grid, cellRow As Integer) As Integer Try Dim node As RowNode = _headNode.RowList(cellRow - _drawStartRow + 1) Return node.RowIndex Catch ex As Exception Return 0 End Try End Function ''' ''' 获取指定行的RowType ''' ''' Public Function GetRowType(grd As Grid, cellRow As Integer) As Integer Try Dim node As RowNode = _headNode.RowList(cellRow - _drawStartRow + 1) Return node.RowType Catch ex As Exception Return 3 End Try End Function Property HeadNode() As RowNode Get Return _headNode End Get Set(value As RowNode) _headNode = value End Set End Property ''' ''' 折叠的列号 ''' ''' Property NodeCol() As Integer Get Return _drawCol End Get Set(value As Integer) _drawCol = value End Set End Property ''' ''' 折叠的起始行号 ''' ''' Property NodeStartRow() As Integer Get Return _drawStartRow End Get Set(value As Integer) _drawStartRow = value End Set End Property ''' ''' 初始化测试站表格 ''' Public Sub InitializeGrid() With _grd LockGridAutoRedraw() .Rows = 1 .Cols = ColNames.Max .DrawMode = DrawModeEnum.OwnerDraw '绘制方式为自绘 .DisplayRowNumber = True '首列显示数字 .ExtendLastCol = True '最后一列自动扩充 '.MultiSelect = False '是否允许选择多行 .FrozenCols = ColNames.Description '冻结列 .BorderStyle = BorderStyleEnum.None .DefaultFont = New Font("微软雅黑", 8) '.DefaultFont = New Font("Consolas", 8) .Range(0, 0, 0, .Cols - 1).Font = New Font($"幼圆", 8) '首行样式 ' .SelectionMode = SelectionModeEnum.ByRow '选中一行 '.BackColor1 = Color.AliceBlue'单行背景色 '.BackColor2 = Color.Azure'双行背景色 .Tree.Row = 2 .Tree.Col = ColNames.Description .Tree.ShowLines = True .Tree.CheckBoxes = False .Tree.Nodes.Clear() For col As Integer = 0 To ColNames.Max - 1 Select Case col Case ColNames.Pause .Cell(0, col).Text = $"P" Case ColNames.Action .Cell(0, col).Text = $"A" Case ColNames.SaveToDb .Cell(0, col).Text = $"S" Case Else .Cell(0, col).Text = [Enum].GetName(GetType(ColNames), col) '设置列名 End Select Next '设置位宽 .Column(ColNames.Step).Width = 40 .Column(ColNames.Label).Width = 80 .Column(ColNames.Result).Width = 80 .Column(ColNames.LowerLimit).Width = 80 .Column(ColNames.UpperLimit).Width = 80 .Column(ColNames.TimeElapsed).Width = 80 .Column(ColNames.Pause).Width = 20 .Column(ColNames.Action).Width = 20 .Column(ColNames.Description).Width = 200 .Column(ColNames.ControlType).Width = 0 .Column(ColNames.CommandType).Width = 80 .Column(ColNames.Command).Width = 120 .Column(ColNames.Parameters).Width = 340 .Column(ColNames.SaveToDb).Width = 20 .Column(ColNames.RecordName).Width = 100 .Column(ColNames.Retry).Width = 40 .Column(ColNames.RetryInterval).Width = 40 .Column(ColNames.ErrorCode).Width = 100 '设置类型 .Column(ColNames.Pause).CellType = CellTypeEnum.CheckBox .Column(ColNames.Action).CellType = CellTypeEnum.CheckBox .Column(ColNames.SaveToDb).CellType = CellTypeEnum.CheckBox .Column(ColNames.ControlType).CellType = CellTypeEnum.ComboBox .Column(ColNames.CommandType).CellType = CellTypeEnum.ComboBox .Column(ColNames.Command).CellType = CellTypeEnum.ComboBox .Column(ColNames.ErrorCode).CellType = CellTypeEnum.ComboBox .ComboBox(ColNames.ControlType).Locked = True .ComboBox(ColNames.CommandType).Locked = True .ComboBox(ColNames.Command).Locked = True .ComboBox(ColNames.ErrorCode).Locked = True '格栅颜色 .GridColor = Color.WhiteSmoke '可见度 UpdateColVisible() '对齐方式 UpdateColAlignment() UnLockGridAutoRedraw() End With End Sub Private Sub UpdateColAlignment() With _grd .Column(ColNames.Step).Alignment = AlignmentEnum.CenterCenter .Column(ColNames.Label).Alignment = AlignmentEnum.RightCenter .Column(ColNames.Pause).Alignment = AlignmentEnum.CenterCenter .Column(ColNames.Action).Alignment = AlignmentEnum.CenterCenter .Column(ColNames.Description).Alignment = AlignmentEnum.LeftCenter .Column(ColNames.ControlType).Alignment = AlignmentEnum.LeftCenter .Column(ColNames.CommandType).Alignment = AlignmentEnum.LeftCenter .Column(ColNames.Command).Alignment = AlignmentEnum.LeftCenter .Column(ColNames.Parameters).Alignment = AlignmentEnum.LeftCenter .Column(ColNames.SaveToDb).Alignment = AlignmentEnum.CenterCenter .Column(ColNames.RecordName).Alignment = AlignmentEnum.LeftCenter .Column(ColNames.Retry).Alignment = AlignmentEnum.RightCenter .Column(ColNames.RetryInterval).Alignment = AlignmentEnum.RightCenter .Column(ColNames.ErrorCode).Alignment = AlignmentEnum.RightCenter End With End Sub Private Sub UpdateColVisible() With _grd .Column(ColNames.Pause).Visible = _debugMode .Column(ColNames.Result).Visible = _debugMode .Column(ColNames.LowerLimit).Visible = _debugMode .Column(ColNames.UpperLimit).Visible = _debugMode .Column(ColNames.TimeElapsed).Visible = _debugMode End With End Sub Private Function ParamsToString(params As List(Of TestCmdParam)) As String Return String.Join($" {_paramChar} ", params.Select(Function(p) p.Value)) End Function Public Sub UpdateGrid2(node As RowNode) Dim row As Integer = node.RowListIndex Dim rowNode As RowNode = _headNode.RowList(row) rowNode.CopyFrom(node) _uploading = True UpdateGrid(_grd, row, rowNode) _uploading = False '触发事件 If SkipEvent Then Return Dim event2 As New PlanNodeSelectChangedEventArgs With {.Node = node, .LineNumber = row, .LineActionEn = node.Action } RaiseEvent PlanNodeSelectChanged(_grd, event2) End Sub Public Sub UpdateGrid(grd As Grid, row As Integer, node As RowNode) Dim rowCmdType As String Dim tmpIsAction As Boolean Dim tmpColor As Color With grd .Cell(row, ColNames.Pause).Text = IIf(node.Pause, "1", "0").ToString() .Cell(row, ColNames.Action).Text = IIf(node.Action, "1", "0").ToString() .Cell(row, ColNames.Label).Text = $"{node.Label}" .Cell(row, ColNames.Description).Text = $"{node.Description}" .Cell(row, ColNames.ControlType).Text = node.ControlType .Cell(row, ColNames.CommandType).Text = $"{node.CommandType}" .Cell(row, ColNames.Command).Text = $"{node.Command}" .Cell(row, ColNames.Parameters).Text = $"{ParamsToString(node.Parameters)}" .Cell(row, ColNames.SaveToDb).Text = $"{node.SaveToDb}" .Cell(row, ColNames.RecordName).Text = $"{node.RecordName}" .Cell(row, ColNames.Retry).Text = $"{node.Retry}" .Cell(row, ColNames.RetryInterval).Text = $"{node.RetryInterval}" .Cell(row, ColNames.ErrorCode).Text = $"{node.ErrorCode}" .Cell(row, ColNames.ErrorMessage).Text = $"{node.ErrorMessage}" rowCmdType = .Cell(row, ColNames.CommandType).Text tmpIsAction = .Cell(row, ColNames.Action).BooleanValue 'tmpColor = setRowTextForeColor(rowCmdType, tmpIsAction, node.RowType) tmpColor = GetRowNodeForeColor(node) If node.RowType = RowNode.RowTypeEnum.FixedModule Then .Range(row, ColNames.Result, row, ColNames.ErrorMessage).FontSize = 10 .Range(row, ColNames.Result, row, ColNames.ErrorMessage).BackColor = Color.PeachPuff .Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = Color.Blue .Range(row, ColNames.Result, row, ColNames.ErrorMessage).FontBold = True .Range(row, ColNames.Result, row, ColNames.ErrorMessage).Locked = True ElseIf node.RowType = RowNode.RowTypeEnum.Module Then If .Cell(row, ColNames.Action).BooleanValue = True Then .Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = Color.DeepPink Else .Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = Color.LightGray End If .Range(row, ColNames.Result, row, ColNames.ErrorMessage).FontSize = 8 .Range(row, ColNames.Result, row, ColNames.ErrorMessage).FontBold = False .Range(row, ColNames.Result, row, ColNames.ErrorMessage).Locked = False Else .Range(row, ColNames.Result, row, ColNames.ErrorMessage).ForeColor = tmpColor .Range(row, ColNames.Result, row, ColNames.ErrorMessage).Locked = False End If End With End Sub Public Sub UpdateGrid(grd As Grid, nodes As RowNodeCollection) For Each node As RowNode In nodes grd.AddItem(node.RowLever, node.Description, String.Empty) Dim row As Integer = grd.Rows - 1 UpdateGrid(grd, row, node) If node.RowNodes.Count > 0 Then UpdateGrid(grd, node.RowNodes) End If Next End Sub ''' ''' 加载测试文件后更新表格 ''' ''' Public Sub UpdateGrid() _uploading = True InitializeGrid() With _grd LockGridAutoRedraw() UpdateGrid(_grd, _headNode.RowNodes) ReflushLabelNames() ReflushRecordNames() UnLockGridAutoRedraw() End With _uploading = False End Sub #Region "表格事件" Private Sub Grid_Click(ByVal sender As Object, ByVal e As EventArgs) If _grd.EditorVisible Then Return '处于编辑状态 Dim point As Point = _grd.PointToClient(Windows.Forms.Cursor.Position) Dim cel As Cell = _grd.HitTest(point.X, point.Y) If cel Is Nothing Then Return If cel.Row < _drawStartRow OrElse cel.Col <> _drawCol Then Return If _headNode Is Nothing Then Return Dim node As RowNode = _headNode.RowList(cel.Row - _drawStartRow + 1) If node Is Nothing Then Return Dim intWidth As Integer = CInt(IIf(_showNodeIcon, 20, 10)) Dim rect As New Rectangle(cel.Bounds.Left + 2 + node.RowLever * intWidth, cel.Bounds.Top + ((cel.Bounds.Height - 9) \ 2), 8, 8) If rect.Contains(point) = False Then Return If node.Expanded Then node.Collapse() LockGridAutoRedraw() For i As Integer = 1 To node.AllChildCount _grd.Row(node.RowListIndex + i).Visible = False Next UnLockGridAutoRedraw() Else node.Expand() LockGridAutoRedraw() ExpandRows(node) UnLockGridAutoRedraw() End If End Sub ''' ''' 展开行节点 ''' ''' Public Sub ExpandRows(node As RowNode) For Each child As RowNode In node.Children _grd.Row(child.RowListIndex).Visible = True '如果子节点上一次为收缩的,则展开依旧为收缩的 If child.Children.Count <= 0 Then Continue For If child.Expanded Then ExpandRows(child) Next End Sub Private Sub CommandChanged(node As RowNode) _grd.Cell(node.RowListIndex, ColNames.Action).Text = IIf(node.Action, "1", "0").ToString _grd.Cell(node.RowListIndex, ColNames.Parameters).Text = ParamsToString(node.Parameters) End Sub Private Sub CommandTypeChanged(node As RowNode) _grd.Cell(node.RowListIndex, ColNames.Action).Text = IIf(node.Action, "1", "0").ToString _grd.Cell(node.RowListIndex, ColNames.Command).Text = node.Command _grd.Cell(node.RowListIndex, ColNames.Parameters).Text = ParamsToString(node.Parameters) End Sub Private Sub ErrCodeChanged(node As RowNode) _grd.Cell(node.RowListIndex, ColNames.ErrorMessage).Text = node.ErrorMessage End Sub Private Sub UpdateNode_ActionChanged(node As RowNode) If node.IsRunning Then For i As Integer = 0 To node.RowNodes.Count - 1 node.Children(i).IsRunning = node.Children(i).Action UpdateNode_ActionChanged(node.Children(i)) Next Else For i As Integer = 0 To node.RowNodes.Count - 1 node.Children(i).IsRunning = node.IsRunning UpdateNode_ActionChanged(node.Children(i)) Next End If End Sub Private Sub Grid_CellChange(sender As Object, e As Grid.CellChangeEventArgs) If _uploading Then Return If _headNode Is Nothing Then Return Dim node As RowNode = _headNode.RowList(e.Row - _drawStartRow + 1) If node Is Nothing Then Return Dim changeType As RowNodeChangedEventArgs.RowNodeChangeType changeType = RowNodeChangedEventArgs.RowNodeChangeType.None Dim beforeNode As RowNode = node.Clone() OnUserAction(beforeNode) Select Case e.Col Case ColNames.[Pause] node.[Pause] = _grd.Cell(e.Row, e.Col).BooleanValue If node.[Pause] Then _grd.Cell(e.Row, e.Col).BackColor = Color.Red Else _grd.Cell(e.Row, e.Col).BackColor = Color.White End If Case ColNames.Action node.Action = _grd.Cell(e.Row, e.Col).BooleanValue changeType = RowNodeChangedEventArgs.RowNodeChangeType.Action If node.RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Cell(e.Row, e.Col).Text = "1" node.Action = _grd.Cell(e.Row, e.Col).BooleanValue End If NodeActionChanged(node) Case ColNames.Description node.Description = _grd.Cell(e.Row, e.Col).Text changeType = RowNodeChangedEventArgs.RowNodeChangeType.Description Case ColNames.[Label] Dim labelName As String = _grd.Cell(e.Row, e.Col).Text If IsExistLabelName(labelName) Then '标签名称冲突检测,不区分大小写 MsgBox($"标签名称[{labelName}]已存在于{GetLabelNameGridRow(labelName)}行,请重新输入!", MsgBoxStyle.Critical, "提示") _uploading = True _grd.Cell(e.Row, e.Col).Text = node.Label _grd.Cell(e.Row, e.Col).SetFocus() _uploading = False Return Else If Not String.IsNullOrEmpty(node.Label) Then RemoveLabelName(node.Label) '移出之前记录标签名称 node.Label = labelName If String.IsNullOrWhiteSpace(node.Label) Then node.RowType = RowNode.RowTypeEnum.Flow Else node.RowType = RowNode.RowTypeEnum.Module AddLabelName(node.Label, e.Row) '记录新的标签名称 End If changeType = RowNodeChangedEventArgs.RowNodeChangeType.Label End If Case ColNames.ControlType node.ControlType = _grd.Cell(e.Row, e.Col).Text If String.IsNullOrWhiteSpace(node.ControlType) Then node.RowType = RowNode.RowTypeEnum.Flow Else node.RowType = RowNode.RowTypeEnum.Control End If changeType = RowNodeChangedEventArgs.RowNodeChangeType.ControlType Case ColNames.CommandType If String.Compare(node.CommandType, _grd.Cell(e.Row, e.Col).Text) <> 0 Then node.CommandType = _grd.Cell(e.Row, e.Col).Text node.Command = "" node.Parameters.Clear() node.Action = Not String.IsNullOrWhiteSpace(node.Command) CommandTypeChanged(node) changeType = RowNodeChangedEventArgs.RowNodeChangeType.CommandType End If NodeActionChanged(node) Case ColNames.Command If node.Command <> _grd.Cell(e.Row, e.Col).Text Then node.Command = _grd.Cell(e.Row, e.Col).Text node.Parameters.Clear() node.Action = Not String.IsNullOrWhiteSpace(node.Command) '拷贝所有参数到当前节点信息中 Dim planCommand As TestCmd = _testCmdManager.GetCommand(node.CommandType, node.Command) If planCommand Is Nothing Then Return For Each cmdParam As TestCmdParam In planCommand.Params node.Parameters.Add(cmdParam.Clone()) Next CommandChanged(node) changeType = RowNodeChangedEventArgs.RowNodeChangeType.Command End If Case ColNames.Parameters Dim str() As String = _grd.Cell(e.Row, e.Col).Text.Split(New Char() {_paramChar}) For i As Integer = 0 To node.Parameters.Count - 1 If i < str.Length Then node.Parameters(i).Value = str(i).Trim() Else node.Parameters(i).Value = String.Empty End If Next changeType = RowNodeChangedEventArgs.RowNodeChangeType.Parameters Case ColNames.SaveToDb node.SaveToDb = _grd.Cell(e.Row, e.Col).BooleanValue changeType = RowNodeChangedEventArgs.RowNodeChangeType.SaveToDb If node.RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Cell(e.Row, e.Col).Text = "0" End If ' NodeAction_Change(_grd, node.RowType, e.Row, node.Action) NodeActionChanged(node) Case ColNames.RecordName Dim recordName As String = _grd.Cell(e.Row, e.Col).Text If IsExistRecordName(recordName) Then MsgBox($"记录名称[{recordName}]已存在于{GetRecordNameGridRow(recordName)}行,请重新输入!", MsgBoxStyle.Critical, "提示") _uploading = True _grd.Cell(e.Row, e.Col).Text = node.Label _grd.Cell(e.Row, e.Col).SetFocus() _uploading = False Return Else If IsExistRecordName(node.RecordName) Then RemoveRecordName(node.RecordName) '移出之前记录名称 node.RecordName = recordName If Not String.IsNullOrWhiteSpace(recordName) Then AddRecordName(node.RecordName, e.Row) '记录新的记录名称 End If changeType = RowNodeChangedEventArgs.RowNodeChangeType.RecordName End If Case ColNames.Retry node.Retry = _grd.Cell(e.Row, e.Col).IntegerValue changeType = RowNodeChangedEventArgs.RowNodeChangeType.Retry Case ColNames.RetryInterval node.RetryInterval = _grd.Cell(e.Row, e.Col).IntegerValue changeType = RowNodeChangedEventArgs.RowNodeChangeType.RetryInterval Case ColNames.ErrorCode node.ErrorCode = _grd.Cell(e.Row, e.Col).Text changeType = RowNodeChangedEventArgs.RowNodeChangeType.ErrorCode Case ColNames.ErrorMessage node.ErrorMessage = _grd.Cell(e.Row, e.Col).Text changeType = RowNodeChangedEventArgs.RowNodeChangeType.ErrorMessage End Select OnUserActionEnd(node) '触发事件 If SkipEvent Then Return Select Case changeType Case RowNodeChangedEventArgs.RowNodeChangeType.None Return End Select StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed Dim args As New RowNodeChangedEventArgs With { .Node = node, .BeforeNode = beforeNode, .ChangeType = changeType } RaiseEvent RowNodeTextChanged(sender, args) End Sub Private _lastSelction As GridSelectRange Private _lastTempSelction As GridSelectRange Private _isSelection As Boolean = False Private Sub Grid_SelChange(sender As Object, e As Grid.SelChangeEventArgs) 'todo:更新详情表格 If _headNode Is Nothing Then Return Dim node As RowNode = _headNode.RowList(_grd.ActiveCell.Row - _drawStartRow + 1) If node Is Nothing Then Return Console.WriteLine($"Grid_SelChange: row:{e.FirstRow} col:{e.FirstCol} end row{e.LastRow} {e.LastCol}") If Not GridNavigationManager.IsRunning Then Dim newSelection As New GridSelectRange With {.StartRow = e.FirstRow, .StartCol = e.FirstCol, .EndRow = e.LastRow, .EndCol = e.LastCol} If _lastSelction IsNot Nothing AndAlso _lastTempSelction IsNot Nothing Then If _lastTempSelction IsNot Nothing AndAlso _lastTempSelction.StartRow = newSelection.StartRow AndAlso _lastTempSelction.StartCol = newSelection.StartCol Then _isSelection = True GridNavigationManager.RemoveForward() GridNavigationManager.Append(New GridNavigation(_grd, _lastSelction, newSelection)) Else If _isSelection Then GridNavigationManager.RemoveForward() GridNavigationManager.Append(New GridNavigation(_grd, _lastSelction, _lastTempSelction)) GridNavigationManager.Append(New GridNavigation(_grd, _lastTempSelction, newSelection)) _lastSelction = _lastTempSelction _isSelection = False Else GridNavigationManager.Append(New GridNavigation(_grd, _lastTempSelction, newSelection)) If _lastSelction Is Nothing OrElse (_lastSelction.StartRow <> _lastTempSelction.StartRow AndAlso _lastSelction.StartCol <> _lastTempSelction.StartCol) Then _lastSelction = _lastTempSelction End If End If _lastTempSelction = newSelection Else _lastTempSelction = newSelection _lastSelction = _lastTempSelction End If End If ActiveNode = node Dim LineNumber As Integer = e.FirstRow Dim LineActionEn As Boolean = node.Action '触发事件 If SkipEvent Then Return Dim event2 As New PlanNodeSelectChangedEventArgs With {.Node = node, .LineNumber = LineNumber, .LineActionEn = LineActionEn } RaiseEvent PlanNodeSelectChanged(sender, event2) End Sub Private Sub Grid_LeaveCell(sender As Object, e As Grid.LeaveCellEventArgs) 'If Not GrdiNavigationManager.IsRunning Then ' Dim lastSelection As New GridSelectRange With {.StartRow = e.Row, .StartCol = e.Col, .EndRow = e.Row, .EndCol = e.Col} ' Dim newSelection As New GridSelectRange With {.StartRow = e.NewRow, .StartCol = e.NewCol, .EndRow = e.NewRow, .EndCol = e.NewCol} ' GrdiNavigationManager.Append(New GridNavigation(_grd, lastSelection, newSelection)) ' Console.WriteLine($"GridNavigation: row:{e.NewRow} col:{e.NewCol} last row{e.Row} {e.Col}") 'End If End Sub Private _dropCol As Integer = 0 Private _dropRow As Integer = 0 Private Sub Grid_ComboDropDown(sender As Object, e As Grid.ComboDropDownEventArgs) _dropRow = e.Row _dropCol = e.Col Select Case e.Col Case ColNames.Command _grd.ComboBox(ColNames.Command).Items.Clear() If _testCmdManager Is Nothing Then Return Dim type As String = _grd.Cell(e.Row, ColNames.CommandType).Text _grd.ComboBox(ColNames.Command).Items.AddRange(_testCmdManager.GetCommandNames(type)) Case ColNames.ControlType _grd.ComboBox(ColNames.ControlType).Items.Clear() If ActiveNode.ParentNode.ControlType = "If" Then _grd.ComboBox(ColNames.ControlType).Items.Add("Then") _grd.ComboBox(ColNames.ControlType).Items.Add("ElseIf") _grd.ComboBox(ColNames.ControlType).Items.Add("Else") Else _grd.ComboBox(ColNames.ControlType).Items.Add("") _grd.ComboBox(ColNames.ControlType).Items.Add("If") _grd.ComboBox(ColNames.ControlType).Items.Add("While") End If End Select End Sub Private Sub Grid_ComboClick(sender As Object, e As Grid.ComboClickEventArgs) Select Case _dropCol Case ColNames.ErrorCode Dim codeMsg As String = _grd.Cell(_dropRow, ColNames.ErrorCode).Text Dim errCode As String = ErrCodeManager.CodeMsgToCode(codeMsg) If String.Compare(ActiveNode.ErrorCode, errCode) <> 0 Then ActiveNode.ErrorCode = errCode ActiveNode.ErrorMessage = _errCodeManager(ActiveNode.ErrorCode).Msg _grd.Cell(ActiveNode.RowListIndex, ColNames.ErrorCode).Text = ActiveNode.ErrorCode _grd.Cell(ActiveNode.RowListIndex, ColNames.ErrorCode).BackColor = _errCodeManager(ActiveNode.ErrorCode).Color _grd.Cell(ActiveNode.RowListIndex, ColNames.ErrorMessage).BackColor = _grd.Cell(ActiveNode.RowListIndex, ColNames.ErrorCode).BackColor ErrCodeChanged(ActiveNode) End If End Select End Sub #End Region #Region "表格操作" Public Sub SetNodeActionShowMode(action As Boolean) If _headNode Is Nothing Then Return LockGridAutoRedraw() For i As Integer = 0 To _headNode.RowList.Count - 1 If _headNode.RowList(i).RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Row(i).Visible = True ElseIf _headNode.RowList(i).RowType = RowNode.RowTypeEnum.Module Then If action = False Then _grd.Row(i).Visible = True Else If _headNode.RowList(i).Action Then _grd.Row(i).Visible = True Else _grd.Row(i).Visible = False For j As Integer = 1 To _headNode.RowList(i).AllChildCount _grd.Row(i + j).Visible = False Next i += _headNode.RowList(i).AllChildCount End If End If Else If action Then If _headNode.RowList(i).Action Then _grd.Row(i).Visible = True Else _grd.Row(i).Visible = False End If Else _grd.Row(i).Visible = True End If End If Next UnLockGridAutoRedraw() End Sub Public Sub SetNodeRecordShowMode(recode As Boolean) If _headNode Is Nothing Then Return LockGridAutoRedraw() For i As Integer = 0 To _headNode.RowList.Count - 1 If _headNode.RowList(i).RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Row(i).Visible = True ElseIf _headNode.RowList(i).RowType = RowNode.RowTypeEnum.Module Then _grd.Row(i).Visible = Not recode Else If recode Then If _headNode.RowList(i).SaveToDb Then _grd.Row(i).Visible = True Else _grd.Row(i).Visible = False End If Else _grd.Row(i).Visible = True End If End If Next UnLockGridAutoRedraw() End Sub Public Sub SetNodeExpand(expand As Boolean) If _headNode Is Nothing Then Return LockGridAutoRedraw() For i As Integer = 1 To _headNode.RowList.Count - 1 If _headNode.RowList(i).RowType = RowNode.RowTypeEnum.FixedModule Then _grd.Row(i).Visible = True ElseIf _headNode.RowList(i).RowType = RowNode.RowTypeEnum.Module Then _headNode.RowList(i).Expanded = expand For Each node As RowNode In _headNode.RowList(i).Children _grd.Row(node.RowListIndex).Visible = expand Next Else If expand Then _grd.Row(i).Visible = True Else If String.IsNullOrEmpty(_headNode.RowList(i).Description) Then _grd.Row(i).Visible = expand End If End If End If Next UnLockGridAutoRedraw() End Sub Public Sub NodesAdd(childNode As RowNode) If _grd.ActiveCell Is Nothing Then Return If _headNode Is Nothing Then Return Dim node As RowNode = _headNode.RowList(_grd.ActiveCell.Row - _drawStartRow + 1) If node Is Nothing Then Return '更新内存 node.AddNode(childNode) '更新控件 NodesAdd2(childNode) End Sub Public Sub NodesAdd2(node As RowNode) If node.RowListIndex = _grd.Rows Then _grd.AddItem("") Else _grd.InsertRow(node.RowListIndex, 1) End If UpdateGrid(_grd, node.RowListIndex, node) If node.Children.Count > 0 Then For Each rowNode As RowNode In node.Children NodesAdd2(rowNode) Next End If End Sub Public Sub NodeAdd(startMoveRow As Integer, rows As Integer) If rows < 1 Then Return If _headNode Is Nothing Then Return Dim cmd As New GridNodeAddCommand(Me, startMoveRow, rows) CommandManager.RunCommand(cmd) '添加到撤销堆栈执行 RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Friend Sub NodeAddCommand(startMoveRow As Integer, rows As Integer, Optional nodes As List(Of RowNode) = Nothing) Dim node As RowNode Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) Dim row As Integer = startMoveRow + rows Dim grdNode As FlexCell.Node = _grd.Tree.FindNode(startMoveRow) LockGridAutoRedraw() _uploading = True For i As Integer = 1 To rows '更新内存 If nodes Is Nothing OrElse nodes.Count < i Then node = New RowNode With {.RowType = RowNode.RowTypeEnum.Flow} Else node = nodes(i - 1) End If '在当前节点后插入节点 startNode.ParentNode.InsertNode(startNode.RowIndex, node) '更新控件 grdNode.Parent.Nodes.Insert(grdNode.Index, "") UpdateGrid(_grd, node.RowListIndex, node) Dim pNode As FlexCell.Node = _grd.Tree.FindNode(node.RowListIndex) AddGridTreeNode(pNode, node) Next '其他操作 _grd.Cell(row, _drawCol).SetFocus() _uploading = False UnLockGridAutoRedraw() End Sub Public Sub NodeDel(startMoveRow As Integer, rows As Integer) If rows < 1 Then Return If _headNode Is Nothing Then Return Dim nodes As New List(Of RowNode) Dim node As RowNode Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) For i As Integer = 1 To rows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If startNode.RowLever <> node.RowLever Then MsgBox("请选择同一级别节点再尝试此操作") '非同级别节点不移动 Return End If nodes.Add(node) Next Dim cmd As New GridNodeDeleteCommand(Me, startMoveRow, rows, nodes) CommandManager.RunCommand(cmd) '添加到撤销堆栈执行 RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Friend Sub NodeDeleteCommand(startMoveRow As Integer, rows As Integer) LockGridAutoRedraw() _uploading = True Dim node As RowNode Dim grdNode As FlexCell.Node Dim row As Integer = startMoveRow - 1 For i As Integer = 1 To rows node = _headNode.RowList(startMoveRow - _drawStartRow + 1) '前面节点已删除,所以每次都是固定位置 If node Is Nothing Then Exit For '更新控件 grdNode = _grd.Tree.FindNode(node.RowListIndex) grdNode.Remove() '更新内存 If node.CanDelete = False Then Exit For node.Remove() '其他操作 StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed Next _grd.Cell(row, _drawCol).SetFocus() _uploading = False UnLockGridAutoRedraw() End Sub Public Sub NodeClear() If _grd.ActiveCell Is Nothing OrElse _grd.Tree.SelectedNode Is Nothing Then Return If _headNode Is Nothing Then Return Dim node As RowNode = _headNode.RowList(_grd.ActiveCell.Row - _drawStartRow + 1) If node Is Nothing Then Return '更新内存 Dim nodeCount As Integer = node.AllChildCount node.Clear() '更新控件 If nodeCount > 0 Then _grd.Tree.SelectedNode.Nodes.Clear() End If '其他操作 StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed End Sub Public Sub NodeMoveUp(startMoveRow As Integer, moveRows As Integer) If _headNode Is Nothing Then Return Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) Dim prevNode As RowNode = startNode.PrevNode If prevNode Is Nothing Then Return Dim node As RowNode For i As Integer = 2 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If startNode.RowLever <> node.RowLever Then MsgBox("请选择同一级别节点再尝试此操作") '非同级别节点不移动 Return End If Next Dim moveEndRow As Integer = prevNode.RowListIndex Dim cmd As New GridNodeMoveUpCommand(Me, startMoveRow, moveRows, moveEndRow) CommandManager.RunCommand(cmd) '添加到撤销堆栈执行 RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Public Sub NodeMoveDown(startMoveRow As Integer, moveRows As Integer) If _headNode Is Nothing Then Return Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) Dim endNode As RowNode = _headNode.RowList(startMoveRow + moveRows - _drawStartRow) Dim nextNode As RowNode = endNode.NextNode If nextNode Is Nothing Then Return Dim node As RowNode For i As Integer = 2 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If startNode.RowLever <> node.RowLever Then MsgBox("请选择同一级别节点再尝试此操作") '非同级别节点不移动 Return End If Next Dim moveEndRow As Integer = startMoveRow + nextNode.AllChildCount + 1 Dim cmd As New GridNodeMoveDownCommand(Me, startMoveRow, moveRows, moveEndRow) CommandManager.RunCommand(cmd) '添加到撤销堆栈执行 RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Friend Sub NodeMoveUpCommand(startMoveRow As Integer, moveRows As Integer) Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) Dim prevNode As RowNode = startNode.PrevNode Dim endNode As RowNode = _headNode.RowList(startMoveRow + moveRows - _drawStartRow) Dim nextNode As RowNode = endNode.NextNode Dim node As RowNode = startNode Dim moveUpRows As Integer = node.AllChildCount + 1 '获取起始节点信息 Dim lstMoveNodes As New List(Of RowNode) Dim lstFixNodes As New List(Of RowNode) Dim isMoveUp As Boolean = True lstMoveNodes.Add(node) For i As Integer = 2 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If node.RowLever < node.RowLever Then Exit For '高于起始节点级别不移动 If node.RowLever > node.RowLever Then Continue For '低于起始节点级别认为是子节点不记录 moveUpRows += node.AllChildCount + 1 lstMoveNodes.Add(node) Next '如果需要上移的节点过多则修改为上一节点下移操作 lstFixNodes.Add(prevNode) isMoveUp = moveUpRows < prevNode.AllChildCount If isMoveUp Then NodeMoveUp(lstFixNodes, lstMoveNodes) Else NodeMoveDown(lstFixNodes, lstMoveNodes) End If End Sub Friend Sub NodeMoveDownCommand(startMoveRow As Integer, moveRows As Integer) Dim endNode As RowNode = _headNode.RowList(startMoveRow + moveRows - _drawStartRow) Dim nextNode As RowNode = endNode.NextNode Dim node As RowNode = endNode Dim moveDownRows As Integer = 0 '获取起始节点信息 Dim lstMoveNodes As New List(Of RowNode) Dim lstFixNodes As New List(Of RowNode) Dim isMoveDown As Boolean = True For i As Integer = 1 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If node.RowLever < node.RowLever Then Exit For '高于起始节点级别不移动 If node.RowLever > node.RowLever Then Continue For '低于起始节点级别认为是子节点不记录 moveDownRows += node.AllChildCount + 1 lstMoveNodes.Add(node) Next '如果需要上移的节点过多则修改为上一节点下移操作 lstFixNodes.Add(nextNode) isMoveDown = moveDownRows < nextNode.AllChildCount If isMoveDown Then NodeMoveDown(lstMoveNodes, lstFixNodes) Else NodeMoveUp(lstMoveNodes, lstFixNodes) End If End Sub Private Sub NodeMoveDown(upNode As List(Of RowNode), downNode As List(Of RowNode)) LockGridAutoRedraw() _uploading = True Dim grdNode As FlexCell.Node Dim grdParentNode As FlexCell.Node Dim preNode As RowNode = downNode(downNode.Count - 1) For Each node As RowNode In upNode grdNode = _grd.Tree.FindNode(node.RowListIndex) grdParentNode = grdNode.Parent node.Remove() preNode.ParentNode.InsertNode(preNode.RowIndex + 1, node) grdNode.Remove() grdParentNode.Nodes.Insert(node.RowIndex, String.Empty) UpdateGrid(_grd, node.RowListIndex, node) '获取表格节点,添加其子节点 Dim pNode As FlexCell.Node = _grd.Tree.FindNode(node.RowListIndex) AddGridTreeNode(pNode, node) preNode = node Next '节点修改 StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed _uploading = False UnLockGridAutoRedraw() End Sub Private Sub NodeMoveUp(upNode As List(Of RowNode), downNode As List(Of RowNode)) LockGridAutoRedraw() _uploading = True Dim grdNode As FlexCell.Node Dim grdParentNode As FlexCell.Node Dim nextNode As RowNode = upNode(0) For Each node As RowNode In downNode grdNode = _grd.Tree.FindNode(node.RowListIndex) grdParentNode = grdNode.Parent node.Remove() nextNode.ParentNode.InsertNode(nextNode.RowIndex, node) grdNode.Remove() grdParentNode.Nodes.Insert(node.RowIndex, String.Empty) UpdateGrid(_grd, node.RowListIndex, node) '获取表格节点,添加其子节点 Dim pNode As FlexCell.Node = _grd.Tree.FindNode(node.RowListIndex) AddGridTreeNode(pNode, node) nextNode = node Next '节点修改 StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed _uploading = False UnLockGridAutoRedraw() End Sub Private Sub AddGridTreeNode(pNode As FlexCell.Node, srcNode As RowNode) For Each node As RowNode In srcNode.RowNodes pNode.Nodes.Insert(node.RowIndex, "") UpdateGrid(_grd, node.RowListIndex, node) AddGridTreeNode(_grd.Tree.FindNode(node.RowListIndex), node) Next End Sub ''' ''' 节点升级 ''' Public Sub NodeMoveLeft(startMoveRow As Integer, moveRows As Integer) If _headNode Is Nothing Then Return Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) If startNode.RowLever <= 1 Then Return Dim startNodeIndex As Integer = startNode.RowIndex Dim node As RowNode Dim moveEndRow As Integer = startNode.ParentNode.RowListIndex + startNode.ParentNode.AllChildCount + 1 For i As Integer = 1 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If startNode.RowLever <> node.RowLever Then MsgBox("请选择同一级别节点再尝试此操作") '非同级别节点不移动 Return End If moveEndRow -= (node.AllChildCount + 1) Next Dim cmd As New GridNodeMoveLeftCommand(Me, startMoveRow, moveRows, moveEndRow, startNodeIndex) CommandManager.RunCommand(cmd) '添加到撤销堆栈执行 RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Public Sub NodeMoveLeftCommand(startMoveRow As Integer, moveRows As Integer) Dim node As RowNode Dim grdNode As FlexCell.Node Dim grdParentNode As FlexCell.Node LockGridAutoRedraw() _uploading = True Dim parentNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1).ParentNode For i As Integer = moveRows To 1 Step -1 node = _headNode.RowList(startMoveRow - _drawStartRow + i) If node Is Nothing Then Exit For If node.RowLever = 0 Then Exit For If node.RowType = RowNode.RowTypeEnum.FixedModule Then Exit For grdNode = _grd.Tree.FindNode(node.RowListIndex) grdParentNode = grdNode.Parent node.MoveLeft() grdNode.Remove() grdParentNode.Parent.Nodes.Insert(grdParentNode.Index + 1, "") UpdateGrid(_grd, node.RowListIndex, node) AddGridTreeNode(_grd.Tree.FindNode(node.RowListIndex), node) StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed Next If parentNode.Children.Count = 0 Then parentNode.RowType = RowNode.RowTypeEnum.Flow NodeRowTypeChanged(parentNode) End If _uploading = False UnLockGridAutoRedraw() End Sub ''' ''' 节点降级 ''' Public Sub NodeMoveRight(startMoveRow As Integer, moveRows As Integer) If _headNode Is Nothing Then Return Dim startNode As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) If startNode.RowLever < 1 Then Return '固定节点不移动 If startNode.PrevNode Is Nothing Then Return '没有上一级节点 Dim node As RowNode For i As Integer = 2 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If startNode.RowLever <> node.RowLever Then MsgBox("请选择同一级别节点再尝试此操作") '非同级别节点不移动 Return End If Next Dim moveRightNodeIndex As Integer = startNode.PrevNode.Children.Count Dim moveEndRow As Integer = startNode.PrevNode.RowListIndex + startNode.PrevNode.AllChildCount + 1 Dim cmd As New GridNodeMoveRightCommand(Me, startMoveRow, moveRows, moveEndRow, moveRightNodeIndex) CommandManager.RunCommand(cmd) '添加到撤销堆栈执行 RaiseEvent PlanGridCommandChanged(Nothing, Nothing) End Sub Public Sub NodeMoveRightCommand(startMoveRow As Integer, moveRows As Integer, nodeIndex As Integer) Dim node As RowNode = _headNode.RowList(startMoveRow - _drawStartRow + 1) Dim parentNode As RowNode = node.PrevNode Dim grdNode As FlexCell.Node = _grd.Tree.FindNode(node.RowListIndex) Dim grdPreNode As FlexCell.Node = grdNode.PrevNode LockGridAutoRedraw() _uploading = True For i As Integer = 1 To moveRows node = _headNode.RowList(startMoveRow - _drawStartRow + i) If node Is Nothing Then Exit For If parentNode.RowLever > node.RowLever Then Continue For If parentNode.RowLever < node.RowLever Then Exit For grdNode = _grd.Tree.FindNode(node.RowListIndex) ' node.MoveRight() node.Remove() parentNode.InsertNode(nodeIndex + i - 1, node) grdNode.Remove() grdPreNode.Nodes.Insert(nodeIndex + i - 1, "") UpdateGrid(_grd, node.RowListIndex, node) AddGridTreeNode(_grd.Tree.FindNode(node.RowListIndex), node) StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed Next If parentNode.RowType = RowNode.RowTypeEnum.Flow Then parentNode.RowType = RowNode.RowTypeEnum.Module NodeRowTypeChanged(parentNode) End If _uploading = False UnLockGridAutoRedraw() End Sub #End Region #Region "外部事件" Public Sub Grid_RowNodeTextChanged(sender As Object, e As RowNodeChangedEventArgs) Dim row As Integer = e.Node.RowListIndex Dim node As RowNode = e.Node Dim cmd As ICommand _uploading = True With _grd Select Case e.ChangeType Case RowNodeChangedEventArgs.RowNodeChangeType.Action .Cell(row, ColNames.Action).Text = IIf(node.Action, "1", "0").ToString() NodeActionChanged(node) Case RowNodeChangedEventArgs.RowNodeChangeType.RowType NodeRowTypeChanged(node) Case RowNodeChangedEventArgs.RowNodeChangeType.Label .Cell(row, ColNames.Label).Text = $"{node.Label}" Case RowNodeChangedEventArgs.RowNodeChangeType.ControlType .Cell(row, ColNames.ControlType).Text = $"{node.ControlType}" Case RowNodeChangedEventArgs.RowNodeChangeType.Description .Cell(row, ColNames.Description).Text = $"{node.Description}" Case RowNodeChangedEventArgs.RowNodeChangeType.SaveToDb .Cell(row, ColNames.SaveToDb).Text = IIf(node.SaveToDb, "1", "0").ToString() Case RowNodeChangedEventArgs.RowNodeChangeType.RecordName .Cell(row, ColNames.RecordName).Text = $"{node.RecordName}" Case RowNodeChangedEventArgs.RowNodeChangeType.Retry .Cell(row, ColNames.Retry).Text = $"{node.Retry}" Case RowNodeChangedEventArgs.RowNodeChangeType.RetryInterval .Cell(row, ColNames.RetryInterval).Text = $"{node.RetryInterval}" Case RowNodeChangedEventArgs.RowNodeChangeType.ErrorCode .Cell(row, ColNames.ErrorCode).Text = $"{node.ErrorCode}" If String.IsNullOrWhiteSpace(node.ErrorCode) = False Then .Cell(row, ColNames.ErrorCode).BackColor = _errCodeManager(node.ErrorCode).Color .Cell(row, ColNames.ErrorMessage).BackColor = .Cell(row, ColNames.ErrorCode).BackColor Else .Cell(row, ColNames.ErrorCode).BackColor = Color.White .Cell(row, ColNames.ErrorMessage).BackColor = Color.White End If Case RowNodeChangedEventArgs.RowNodeChangeType.ErrorMessage .Cell(row, ColNames.ErrorMessage).Text = $"{node.ErrorMessage}" Case RowNodeChangedEventArgs.RowNodeChangeType.CommandType If String.Compare(.Cell(row, ColNames.CommandType).Text, node.CommandType) <> 0 Then .Cell(row, ColNames.CommandType).Text = $"{node.CommandType}" CommandTypeChanged(node) NodeActionChanged(node) End If Case RowNodeChangedEventArgs.RowNodeChangeType.Command If String.Compare(.Cell(row, ColNames.Command).Text, node.Command) <> 0 Then .Cell(row, ColNames.Command).Text = $"{node.Command}" CommandChanged(node) NodeActionChanged(node) End If Case RowNodeChangedEventArgs.RowNodeChangeType.Parameters .Cell(row, ColNames.Parameters).Text = $"{ParamsToString(node.Parameters)}" End Select End With OnUserAction(e.BeforeNode) OnUserActionEnd(e.Node) 'If CommandManager.IsRuning = False Then ' Dim dic As New Dictionary(Of Integer, TextChangedRowNode) From { ' {row, New TextChangedRowNode With {.BeforeRowNode = e.BeforeNode.Clone, .AfterRowNode = e.Node.Clone}} ' } ' CommandManager.AddUndoCommand(New GridNodeTextChangedCommand(Me, dic)) ' RaiseEvent PlanGridCommandChanged(Nothing, Nothing) 'End If StationEditStatusMonitor.StationEditStatus = StationEditStatusMonitor.StationEditStatusEnum.Changed _uploading = False End Sub Public Function CheckRecordDuplicateName() As Boolean Dim recodeNames As New Dictionary(Of String, Integer) For Each node As RowNode In _headNode.RowList If node.SaveToDb Then If String.IsNullOrWhiteSpace(node.RecordName) Then If MsgBox($"Record Name 无效!" & vbNewLine & "行号: " & node.RowListIndex & vbNewLine & "RecordName: [" & node.RecordName & "]" & vbNewLine & "是否继续操作?", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then Return False Else If recodeNames.ContainsKey(node.RecordName) Then If MsgBox("Record Name 重名!" & vbNewLine & "当前行号: " & node.RowListIndex & vbNewLine & "冲突行号: " & recodeNames(node.RecordName) & vbNewLine & "RecordName: " & node.RecordName & vbNewLine & vbNewLine & "请注意,记录名不能重复,否则前面的数据将会被覆盖!是否继续操作?", MsgBoxStyle.OkCancel ) = MsgBoxResult.Cancel Then Return False Else recodeNames.Add(node.RecordName, node.RowListIndex) End If End If End If Next Return True End Function ''' ''' 反显节点所在行 ''' ''' Public Sub TestNodeChanged(node As RowNode) _grd.Cell(node.RowListIndex, ColNames.Action).EnsureVisible() _grd.Cell(node.RowListIndex, ColNames.Action).BackColor = Color.Blue _grd.Range(node.RowListIndex, 1, node.RowListIndex, _grd.Cols - 1).SelectCells() End Sub Public Sub NodeCompleted(node As RowNode, testReturn As TestCommandReturn) Dim row As Integer = node.RowListIndex _grd.Cell(row, ColNames.Action).BackColor = CType(IIf(testReturn.ExecuteResult, Color.Green, Color.Red), Color) _grd.Cell(row, ColNames.Result).Text = testReturn.RecordValue _grd.Cell(row, ColNames.LowerLimit).Text = testReturn.LowerLimit _grd.Cell(row, ColNames.UpperLimit).Text = testReturn.UpperLimit _grd.Cell(row, ColNames.TimeElapsed).Text = testReturn.StepTimeSpan.TotalMilliseconds.ToString("N0") End Sub Public Sub ClearDebug() For i As Integer = 1 To _grd.Rows - 1 _grd.Cell(i, ColNames.Action).BackColor = Color.White _grd.Cell(i, ColNames.LowerLimit).Text = "" _grd.Cell(i, ColNames.UpperLimit).Text = "" _grd.Cell(i, ColNames.TimeElapsed).Text = "" _grd.Cell(i, ColNames.Result).Text = "" Next End Sub #End Region Public Enum ColNames ''' ''' 步骤,固定 ''' [Step] ''' ''' 断点执行,固定列 ''' [Pause] ''' ''' 是否运行 ''' Action ''' ''' 调试结果 ''' Result ''' ''' 节点下限 ''' LowerLimit ''' ''' 节点上限 ''' UpperLimit ''' ''' 节点测试耗时 ''' TimeElapsed ''' ''' 模块名称 ''' [Label] ''' ''' 节点解析 ''' Description ''' ''' 节点控制执行类型 ''' ControlType ''' ''' 命令类型 ''' CommandType ''' ''' 命令关键字 ''' Command ''' ''' 执行命令参数 ''' Parameters ''' ''' 失败重试次数 ''' Retry ''' ''' 重试间隔 ''' RetryInterval ''' ''' 当前返回值是否记录入库 ''' SaveToDb ''' ''' 返回值变量名 ''' RecordName ''' ''' 错误代码 ''' ErrorCode ''' ''' 错误提示 ''' ErrorMessage Max End Enum End Class End Namespace