Imports System.ComponentModel Imports System.Text Imports System.Timers Imports System.Xml Imports BLV_Studio.EnumExtend Imports FlexCell Imports Newtonsoft.Json Namespace GridModel Public Class TipChangedEventArgs Inherits EventArgs Public Property Title As String ''' ''' 提示信息 ''' ''' Public Property TipString As String Sub New(title As String, tip As String) Me.Title = title TipString = tip End Sub End Class Public Class OutputPrintEventArgs Inherits EventArgs Sub New(tp As Types, txt As String) Type = tp Text = txt End Sub ''' ''' 输出的类型 ''' ''' Public Property Type As Types ''' ''' 输出的文本的内容 ''' ''' Public Property Text As String Enum Types ''' ''' 普通信息 ''' [Info] ''' ''' 警告信息 ''' Warn ''' ''' 错误信息 ''' [Error] End Enum End Class Public Class DeviceEventModel Public _isVisible_Attributes As Boolean = True Public _isVisible_Port As Boolean = True Public _isVisible_Action As Boolean = True Public _isVisible_Scenes As Boolean = True Public _isVisible_Conditions As Boolean = True Public _RcuModelName As String = "" ''' ''' 资源管理器对象 ''' Public _rsmObject As RowNodeCompile ''' ''' 资源管理器treeview根节点 ''' Public _rsm_rootNode As New rsmTreeNode Public _rsm_node_objectGroups As New rsmTreeNode Public _rsm_node_actionGroups As New rsmTreeNode Public _rsm_node_contextualGroups As New rsmTreeNode Public _rsm_node_xiaobao As New rsmTreeNode ''' ''' 设备键值对(用于对应资源管理器TreeView Node与RowNode) ''' Public _rsm_KeyPair_objectGroups As Dictionary(Of Integer, RowNode) ''' ''' 动作键值对(用于对应资源管理器TreeView Node与RowNode) ''' Public _rsm_KeyPair_actionGroups As Dictionary(Of Integer, RowNode) ''' ''' 场景键值对(用于对应资源管理器TreeView Node与RowNode) ''' Public _rsm_KeyPair_contextualGroups As Dictionary(Of Integer, RowNode) ''' ''' 小宝键值对(用于对应资源管理器TreeView Node与RowNode) ''' Public _rsm_KeyPair_xiaobao As Dictionary(Of Integer, RowNode) #Region "表格属性" ''' 绘制表格图标API Private Declare Function DrawIconEx Lib "user32" (hDC As IntPtr, xLeft As Integer, yTop As Integer, hIcon As IntPtr, cxWidth As Integer, cyWidth As Integer, ByVal istepIfAniCur As Integer, ByVal hbrFlickerFreeDraw As Integer, ByVal diFlags As Integer) As Integer Private Const DI_NORMAL As Integer = &H3 ''' 提示信息改变事件 Public Event TipChanged(sender As Object, e As TipChangedEventArgs) ''' 输出信息打印 Public Event OutputPrint(sender As Object, e As OutputPrintEventArgs) Public _grdErrLst As FlexCell.Grid Public _ruleChk_ErrCnt As Integer Public _ruleChk_WarningCnt As Integer ''' TreeView 控件 Public _tv As TreeView ''' 进度条 控件 Public _tsp As ToolStripProgressBar ''' 表格控件 Public _grd As FlexCell.Grid ''' 树状目录跟节点,不参与显示 Public _rootNode As RowNode ''' 撤销重做管理器 Private _undoManager As CommandManager ''' 表格编译器 Public _compiler As RowNodeCompile ''' 已使用设备类型管理器 Private _usedDevTypes As UsedDeviceTypes ''' 忽略鼠标移动事件 Private _skipMouseMoveChange As Boolean ''' 文件是否有修改,如果有修改,则在关闭时提示保存 Public _isCellChanged As Boolean ''' 当前是否按下Ctrl键 Private _flgControl As Boolean ''' 默认行高 Private ReadOnly _defaultRowHeight As Short ''' 默认字体大小 Private ReadOnly _defaultFontSize As Single ''' 刷新锁计数 Private _autoRedraw As Integer ''' 树状节点显示起始行 Private _drawRow As Integer ''' 树状节点显示绘制列 Private _drawCol As Integer ''' 当前放大倍数 Private _zoomNum As Single = 1 ''' 动作参数最大数量 Private Const MaxParamCount As Integer = 6 ''' 默认列宽 Private ReadOnly _defaultColumnWidths As List(Of Short) ''' 基类文件名 Public BasicClassFilename As String ''' 条件文件名 Public ConditionFileName As String ''' ''' 树状节点绘制图标 ''' ''' Public Property ShowNodeIcon As Boolean ''' ''' 忽略单元格改变事件 ''' ''' Protected Friend Property SkipCellChange As Boolean ''' ''' 设备对象基类信息 ''' ''' Public Property BasicClasses As DeviceObjectClasses ''' ''' 条件 ''' ''' Public Property Condictions As ConfigActionConcitons '事件层级节点关系(2022-04-12) 'DeviceEventConditionItem '| '|-- DeviceEventAllConditions '| |DeviceEventConditions '| |DeviceEventConditions '| '|-- DeviceEventActions '| |DeviceEventAction '| |DeviceEventAction ''' ''' 模型关联的treeView控件,用于资源管理器浏览 Momo 0422 ''' ''' Public Property TV As TreeView Get Return _tv End Get Set(value As TreeView) _tv = value RemoveHandler _tv.DoubleClick, AddressOf Tv_DoubleClick AddHandler _tv.DoubleClick, AddressOf Tv_DoubleClick End Set End Property Public Property GridErrList As Grid Get Return _grdErrLst End Get Set(value As Grid) _grdErrLst = value 'RemoveHandler _grdErrLst.OwnerDrawCell, AddressOf GridErrLst_OwnerDrawCell 'RemoveHandler _grdErrLst.Click, AddressOf GridErrLst_Click RemoveHandler _grdErrLst.DoubleClick, AddressOf GridErrLst_DoubleClick 'RemoveHandler _grdErrLst.ComboDropDown, AddressOf GridErrLst_ComboDropDown 'RemoveHandler _grdErrLst.ComboClick, AddressOf GridErrLst_ComboClick 'RemoveHandler _grdErrLst.CellChange, AddressOf GridErrLst_CellChange 'RemoveHandler _grdErrLst.SelChange, AddressOf GridErrLst_SelChange 'RemoveHandler _grdErrLst.KeyDown, AddressOf GridErrLst_KeyDown 'RemoveHandler _grdErrLst.KeyUp, AddressOf GridErrLst_KeyUp RemoveHandler _grdErrLst.MouseMove, AddressOf GridErrLst_MouseMove 'RemoveHandler _grdErrLst.MouseWheel, AddressOf GridErrLst_MouseWheel 'RemoveHandler _grdErrLst.LeaveCell, AddressOf GridErrLst_LeaveCell 'RemoveHandler _grdErrLst.MouseDown, AddressOf GridErrLst_MouseDown 'RemoveHandler _grdErrLst.MouseUp, AddressOf GridErrLst_MouseUp '’AddHandler _grdErrLst.MouseWheel, AddressOf GridErrLst_MouseWheel AddHandler _grdErrLst.MouseMove, AddressOf GridErrLst_MouseMove 'AddHandler _grdErrLst.KeyUp, AddressOf GridErrLst_KeyUp 'AddHandler _grdErrLst.KeyDown, AddressOf GridErrLst_KeyDown 'AddHandler _grdErrLst.SelChange, AddressOf GridErrLst_SelChange 'AddHandler _grdErrLst.CellChange, AddressOf GridErrLst_CellChange 'AddHandler _grdErrLst.ComboDropDown, AddressOf GridErrLst_ComboDropDown 'AddHandler _grdErrLst.ComboClick, AddressOf GridErrLst_ComboClick 'AddHandler _grdErrLst.Click, AddressOf GridErrLst_Click AddHandler _grdErrLst.DoubleClick, AddressOf GridErrLst_DoubleClick 'AddHandler _grdErrLst.OwnerDrawCell, AddressOf GridErrLst_OwnerDrawCell 'AddHandler _grdErrLst.LeaveCell, AddressOf GridErrLst_LeaveCell 'AddHandler _grdErrLst.MouseDown, AddressOf GridErrLst_MouseDown 'AddHandler _grdErrLst.MouseUp, AddressOf GridErrLst_MouseUp End Set End Property ''' ''' 模型关联的表格控件 ''' ''' Public Property Grid As Grid Get Return _grd End Get Set(value As Grid) _grd = value RemoveHandler _grd.OwnerDrawCell, AddressOf Grid_OwnerDrawCell RemoveHandler _grd.Click, AddressOf Grid_Click RemoveHandler _grd.DoubleClick, AddressOf Grid_DoubleClick RemoveHandler _grd.ComboDropDown, AddressOf Grid_ComboDropDown RemoveHandler _grd.ComboClick, AddressOf Grid_ComboClick RemoveHandler _grd.CellChange, AddressOf Grid_CellChange RemoveHandler _grd.SelChange, AddressOf Grid_SelChange RemoveHandler _grd.KeyDown, AddressOf Grid_KeyDown RemoveHandler _grd.KeyUp, AddressOf Grid_KeyUp RemoveHandler _grd.MouseMove, AddressOf Grid_MouseMove RemoveHandler _grd.MouseWheel, AddressOf Grid_MouseWheel RemoveHandler _grd.LeaveCell, AddressOf Grid_LeaveCell RemoveHandler _grd.MouseDown, AddressOf Grid_MouseDown RemoveHandler _grd.MouseUp, AddressOf Grid_MouseUp AddHandler _grd.MouseWheel, AddressOf Grid_MouseWheel AddHandler _grd.MouseMove, AddressOf Grid_MouseMove AddHandler _grd.KeyUp, AddressOf Grid_KeyUp AddHandler _grd.KeyDown, AddressOf Grid_KeyDown AddHandler _grd.SelChange, AddressOf Grid_SelChange AddHandler _grd.CellChange, AddressOf Grid_CellChange AddHandler _grd.ComboDropDown, AddressOf Grid_ComboDropDown AddHandler _grd.ComboClick, AddressOf Grid_ComboClick AddHandler _grd.Click, AddressOf Grid_Click AddHandler _grd.DoubleClick, AddressOf Grid_DoubleClick AddHandler _grd.OwnerDrawCell, AddressOf Grid_OwnerDrawCell AddHandler _grd.LeaveCell, AddressOf Grid_LeaveCell AddHandler _grd.MouseDown, AddressOf Grid_MouseDown AddHandler _grd.MouseUp, AddressOf Grid_MouseUp End Set End Property #End Region #Region "模型内容填充行节点" ''' ''' 添加酒店房型节点 ''' ''' 酒店房型模型信息 ''' Private Function AppendHotelRoomTypeNode(model As DeviceModel) As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.HotelRoomType node.Name = $"{model.HotelRoomType}" node.Text = "项目名称:" & $"{model.HotelRoomType}({model.VerdorName} - {model.HotelName})" node.Tag = New HotelRoomTypeRowNodeTag With {.HotelName = model.HotelName, .HotelRoomType = model.HotelRoomType, .VerdorName = model.VerdorName} '添加主机模型 node.AddNode(AppendDeviceModelNode(model)) '添加情景模式 node.AddNode(AppendContextualModels) '添加动作组集合 node.AddNode(AppendAllActions) Return node End Function ''' ''' 添加场景模式集合节点 ''' ''' Private Function AppendContextualModels() As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.ContextualModels node.Name = "场景模式集" node.Text = "场景模式集:" node.AddNode(CreateRowNode(RowNode.RowTypeEnum.ContextualModel)) Return node End Function ''' ''' 添加动作组集合节点 ''' ''' Private Function AppendAllActions() As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.DeviceEventAllActions node.Name = "动作组集合" node.Text = "动作组集合:" node.AddNode(CreateRowNode(RowNode.RowTypeEnum.DeviceEventActions)) Return node End Function ''' ''' 添加设备模型节点 ''' ''' 设备模型的模型信息 ''' Private Function AppendDeviceModelNode(model As DeviceModel, Optional isInterval As Boolean = False) As RowNode Dim tipStr As String Dim type As RowNode.RowTypeEnum If isInterval Then tipStr = "外设" type = RowNode.RowTypeEnum.ExternalModel Else type = RowNode.RowTypeEnum.Model tipStr = "主机" End If Dim node As New RowNode node.RowType = type node.Name = model.Name node.Text = $"{tipStr}:{model.Name}" node.Tag = New ModelRowNodeTag With {.Desc = model.Desc} '填充主机属性 Dim configNode As New RowNode configNode.RowType = RowNode.RowTypeEnum.ModelAttributes configNode.Name = $"{tipStr}属性集合" configNode.Text = $"{tipStr}属性" node.AddNode(configNode) Dim ConfigGroup_CfgType As RowNode.CfgTypeEnum If model.Config IsNot Nothing Then For Each group As DeviceModelConfigGroup In model.Config Dim groupNode As RowNode = AppendDeviceModelAttributeGroupNode(group) configNode.AddNode(groupNode) Select Case group.CFG_Type Case "XiaoBaoCMD" ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_XiaoBaoCMD Case "DeviceExists" ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_DeviceExists Case "Default" ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_Default Case Else ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_Default End Select For Each config As DeviceChildNodeAttribute In group.Attributes groupNode.AddNode(AppendDeviceModelAttributeNode(config, ConfigGroup_CfgType, group.CFG_Value)) Next Next End If '填充设备组 If model.Nodes IsNot Nothing Then For Each group As DeviceChildNodeClass In model.Nodes node.AddNode(AppendDeviceGroupNode(group)) Next End If Return node End Function ''' ''' 添加设备模型属性组节点 ''' ''' 设备模型属性组模型 ''' Private Function AppendDeviceModelAttributeGroupNode(model As DeviceModelConfigGroup) As RowNode Dim node As New RowNode node.Name = model.Name Select Case model.CFG_Type Case "XiaoBaoCMD" node.RowType = RowNode.RowTypeEnum.ModelAttributes_XiaoBaoCMD node.Text = $"词条组:{model.Name}" Case "DeviceExists" node.RowType = RowNode.RowTypeEnum.ModelAttributes_DeviceExists node.Text = $"设备存在组:{model.Name}" Case Else node.RowType = RowNode.RowTypeEnum.ModelAttributeGroup node.Text = $"属性组:{model.Name}" End Select Return node End Function ''' ''' 添加设备模型属性节点 ''' ''' 设备模型属性模型 ''' Private Function AppendDeviceModelAttributeNode(model As DeviceChildNodeAttribute, Optional Attribute_CfgType As RowNode.CfgTypeEnum = RowNode.CfgTypeEnum.CfgType_Default, Optional CFG_Value As String = "") As RowNode Dim node As New RowNode node.Name = model.Name Select Case Attribute_CfgType Case RowNode.CfgTypeEnum.CfgType_XiaoBaoCMD node.RowType = RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD node.Text = $"词条:{model.Name}" node.Tag = New XiaoBaoRowNodeTag(CFG_Value, model.DataDefault) Case RowNode.CfgTypeEnum.CfgType_DeviceExists node.RowType = RowNode.RowTypeEnum.ModelAttribute_DeviceExists node.Text = $"存在:{model.Name}" node.DeviceType = model.DataDefault node.Tag = New AttributeRowNodeTag(model.Name, model.DataType, model.DataRange, model.DataRangeValue, model.Desc, model.DataDefault) Case Else node.RowType = RowNode.RowTypeEnum.ModelAttribute node.Text = $"属性:{model.Name}" node.DeviceType = model.DataDefault node.Tag = New AttributeRowNodeTag(model.Name, model.DataType, model.DataRange, model.DataRangeValue, model.Desc, model.DataDefault) End Select Return node End Function ''' ''' 添加设备对象组对象 ''' ''' 设备对象模型 ''' Private Function AppendDeviceGroupNode(model As DeviceChildNodeClass) As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.DeviceGroup node.Name = $"{model.Name}" node.Text = "设备组:" & model.Name ''2022-05-23 Momo 编译设备存在时,结合 interface、DevTypeData、Protocol_Ver 来确定设备存在 node.Interface = model.Interface node.DEV_TYPE_DATA = model.DEV_TYPE_DATA '2022-05-23 Momo V3.0 设备组新增 Dev_Type_Data node.PROTOCOL_VER = model.PROTOCOL_VER '2022-05-23 Momo V3.0 设备组新增 Protocol_Ver ''2022-05-23 Momo -------------end If model.Nodes Is Nothing Then Return node For Each dev As DeviceChildNode In model.Nodes node.AddNode(AppendDeviceObjectNode(dev)) Next Return node End Function ''' ''' 添加设备对象节点 ''' ''' 设备对象模型 ''' 填充设备节点下的子节点 ''' Private Function AppendDeviceObjectNode(model As DeviceChildNode, Optional addChildNode As Boolean = True) As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.DeviceObject node.Name = model.Name node.DeviceAlias = model.DefaultAliasName node.Interface = model.Interface '节点接口类型 If model.Interface = "RS485Active" OrElse model.Interface = "RS485Polling" Then node.Text = "设备:" & model.Name Else node.Text = "端口:" & model.Name End If node.Tag = New DeviceObjectRowNodeTag With {.Device = model} If addChildNode = False Then Return node If model.DefaultClass IsNot Nothing AndAlso String.IsNullOrEmpty(model.DefaultClass) = False Then node.DeviceType = model.DefaultClass '添加子节点 FillDeviceObjectNode(node) End If Return node End Function ''' ''' 根据设备类型填充设备节点下内容 ''' ''' 设备节点 Protected Friend Sub FillDeviceObjectNode(node As RowNode, Optional addUsed As Boolean = True) node.Clear() Dim objectType As DeviceObjectType = BasicClasses.FindDeviceClass(node.DeviceType) If objectType IsNot Nothing Then If objectType.Attributes.Count > 0 Then '添加属性集 Dim attributesNode As New RowNode attributesNode.RowType = RowNode.RowTypeEnum.DeviceAttributes attributesNode.Name = $"设备属性集合" attributesNode.Text = $"设备属性:" node.AddNode(attributesNode) '填充属性集 FillObjectAttributes(attributesNode, objectType) End If If objectType.Events.Count > 0 Then '添加事件集 Dim evenstNode As New RowNode evenstNode.RowType = RowNode.RowTypeEnum.DeviceEvents evenstNode.Text = $"设备事件:" node.AddNode(evenstNode) '填充事件集 FillObjectEvents(evenstNode, objectType) End If End If '记录设备类型与设备名称(移除相同行节点) If addUsed Then _usedDevTypes.AddNode(node) End Sub ''' ''' 填充设备属性组内容 ''' ''' 属性组节点 ''' 设备对象基类模型 Private Sub FillObjectAttributes(pNode As RowNode, objectType As DeviceObjectType) For Each att As DeviceChildNodeAttribute In objectType.Attributes '添加属性 pNode.AddNode(AppendObjectAttribute(att)) Next End Sub ''' ''' 创建新的设备属性节点 ''' ''' 属性模型 ''' Private Function AppendObjectAttribute(model As DeviceChildNodeAttribute) As RowNode Dim attributeNode As New RowNode attributeNode.RowType = RowNode.RowTypeEnum.DeviceAttribute attributeNode.Name = model.Name attributeNode.Text = $"属性:{model.Name}" attributeNode.DeviceType = model.DataDefault attributeNode.Tag = New AttributeRowNodeTag(model.Name, model.DataType, model.DataRange, model.DataRangeValue, model.Desc, model.DataDefault) Return attributeNode End Function ''' ''' 填充设备事件组内容 ''' ''' 事件组节点 ''' 设备对象基类模型 Private Sub FillObjectEvents(pNode As RowNode, objectType As DeviceObjectType) For Each eve As DeviceChildNodeEvent In objectType.Events '添加事件 pNode.AddNode(AppendObjectEvent(eve)) Next End Sub ''' ''' 创建新的设备事件节点 ''' ''' 事件模型 ''' Private Function AppendObjectEvent(model As DeviceChildNodeEvent, Optional addCondition As Boolean = True) As RowNode Dim eventNode As New RowNode eventNode.RowType = RowNode.RowTypeEnum.DeviceEvent eventNode.Name = model.Name eventNode.Text = $"事件:{model.Name}" eventNode.DeviceType = "场景" '事件默认为DeviceType = 场景,以便小宝调用 eventNode.Tag = New DeviceEventRowNodeTag With {.Name = model.Name, .DataValue = model.DataValue, .Description = model.Desc} If addCondition Then eventNode.AddNode(CreateRowNode(RowNode.RowTypeEnum.DeviceEventConditionItem)) Return eventNode End Function ''' ''' 添加执行方式节点 ''' ''' 执行方式模型 ''' Private Function AppendActionMode(exeMode As Conction) As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.DeviceEventActionMode node.Name = exeMode.Name node.Text = exeMode.Name node.DeviceType = exeMode.DataDefault node.Tag = New AttributeRowNodeTag(exeMode.Name, exeMode.DataType, exeMode.DataRange, exeMode.DataRangeValue, exeMode.Desc, exeMode.DataDefault) Return node End Function ''' ''' 添加执行条件节点 ''' ''' 执行条件模型 ''' Private Function AppendActionCondition(condiction As Conction) As RowNode Dim node As New RowNode node.RowType = RowNode.RowTypeEnum.DeviceEventConditions node.Name = condiction.Name node.Text = condiction.Name node.DeviceType = condiction.DataDefault node.Tag = New AttributeRowNodeTag(condiction.Name, condiction.DataType, condiction.DataRange, condiction.DataRangeValue, condiction.Desc, condiction.DataDefault) Return node End Function ''' ''' 添加已使用别名的节点 ''' ''' Public Sub AddUsedTypes(node As RowNode) _usedDevTypes.AddNode(node) End Sub ''' ''' 当节点名被清空时,移除该节点 ''' ''' Public Sub RemoveUsedTypes(node As RowNode) _usedDevTypes.RemoveNode(node) End Sub #End Region #Region "行节点填充表格" ''' ''' 初始化表格时,传入根节点初始化表格 ''' ''' Private Sub FillGridByRootNode(node As RowNode, Optional isaddintem As Boolean = True) LockGridAutoRedraw() If isaddintem Then _grd.AddItem("", False) End If '填充已使用设备类型 _usedDevTypes.AddNode(node) '’FillRowStyle(node) FillRowText(node) For Each n As RowNode In node.Nodes FillGridByRootNode(n, isaddintem) Next UnLockGridAutoRedraw() End Sub ''' ''' 移除当前节点行 ''' ''' Protected Friend Sub RemoveNodeRow(node As RowNode) LockGridAutoRedraw() _grd.Range(node.RowListIndex, 1, node.RowListIndex + node.AllChildCount, 1).DeleteByRow() node.Remove() UnLockGridAutoRedraw() End Sub ''' ''' 移除节点的子行 ''' ''' Protected Friend Sub RemoveNodeChildRow(node As RowNode) If node.RowListIndex = _grd.Rows - 1 Then Return If node.Count = 0 Then Return LockGridAutoRedraw() If node.RowType = RowNode.RowTypeEnum.DeviceObject Then _usedDevTypes.RemoveNode(node) _grd.Range(node.RowListIndex + 1, 1, node.RowListIndex + node.AllChildCount, 1).DeleteByRow() node.Clear() UnLockGridAutoRedraw() End Sub ''' ''' 根据节点信息,添加表格行 ''' ''' 需要添加的行节点信息 ''' 是否包含当前节点的子节点 Protected Friend Sub AddNodeRow(node As RowNode, Optional containsChildNode As Boolean = False) LockGridAutoRedraw() With _grd If node.RowListIndex = .Rows Then '最后一行 .AddItem("", False) .Row(node.RowListIndex).Visible = True ElseIf node.RowListIndex < .Rows Then '表格内 .InsertRow(node.RowListIndex, 1) .Row(node.RowListIndex).Visible = True Else Throw New Exception($"无效的行号:{node.RowListIndex}") End If End With FillRowStyle(node) FillRowText(node) If containsChildNode Then AddNodeChildRow(node, containsChildNode) End If UnLockGridAutoRedraw() End Sub ''' ''' 添加当前节点的所有子节点的内容至表格行 ''' ''' 需要添加的行节点信息 ''' 是否包含当前节点的子节点 Protected Friend Sub AddNodeChildRow(node As RowNode, Optional containsChildNode As Boolean = False) LockGridAutoRedraw() For Each cNode As RowNode In node.Nodes AddNodeRow(cNode, containsChildNode) Next UnLockGridAutoRedraw() End Sub ''' ''' 根据行节点内容填充表格文本内容 ''' ''' Protected Friend Sub FillRowText(node As RowNode) With _grd .Cell(node.RowListIndex, ColNames.Action).Text = node.Action .Cell(node.RowListIndex, ColNames.DeviceAlias).Text = node.DeviceAlias .Cell(node.RowListIndex, ColNames.Node).Text = node.Text Select Case node.RowType Case RowNode.RowTypeEnum.HotelGroup Case RowNode.RowTypeEnum.Hotel Case RowNode.RowTypeEnum.HotelRoomType Case RowNode.RowTypeEnum.Model Case RowNode.RowTypeEnum.ModelAttributes Case RowNode.RowTypeEnum.ModelAttributeGroup Case RowNode.RowTypeEnum.ModelAttribute .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType Case RowNode.RowTypeEnum.DeviceGroup Case RowNode.RowTypeEnum.DeviceObject .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType .Cell(node.RowListIndex, ColNames.DeviceName).Text = node.DeviceName .Cell(node.RowListIndex, ColNames.DeviceMothed).Text = node.DeviceMothed Case RowNode.RowTypeEnum.DeviceAttributes '设备对象属性集合 Case RowNode.RowTypeEnum.DeviceAttribute '设备对象属性 .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType Case RowNode.RowTypeEnum.DeviceEvents .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType Case RowNode.RowTypeEnum.DeviceEvent '事件 .Cell(node.RowListIndex, ColNames.DeviceName).Text = node.DeviceName .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType '事件赋予设备类型=场景 '.Cell(node.RowListIndex, ColNames.DeviceMothed).Text = node.eventId Case RowNode.RowTypeEnum.DeviceEventActionMode '执行方式 .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType Case RowNode.RowTypeEnum.DeviceEventConditions '事件条件 .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType 'Case RowNode.RowTypeEnum.DeviceEventConditionItem ' .Cell(node.RowListIndex, ColNames.DeviceMothed).Text = node.eventId Case RowNode.RowTypeEnum.ContextualModels Case RowNode.RowTypeEnum.ContextualModel '25 情景模式 .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType .Cell(node.RowListIndex, ColNames.DeviceName).Text = node.DeviceName Case RowNode.RowTypeEnum.DeviceEventAllActions Case RowNode.RowTypeEnum.DeviceEventActions '22 动作组 .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType .Cell(node.RowListIndex, ColNames.DeviceName).Text = node.DeviceName .Cell(node.RowListIndex, ColNames.DeviceMothed).Text = node.DeviceMothed Case RowNode.RowTypeEnum.ModelAttribute_DeviceExists .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType .Cell(node.RowListIndex, ColNames.DeviceName).Text = node.DeviceName Case RowNode.RowTypeEnum.DeviceEventAction '23 动作’ .Cell(node.RowListIndex, ColNames.DeviceType).Text = node.DeviceType .Cell(node.RowListIndex, ColNames.DeviceName).Text = node.DeviceName .Cell(node.RowListIndex, ColNames.DeviceMothed).Text = node.DeviceMothed .Cell(node.RowListIndex, ColNames.DelayTime).Text = node.DelayTime .Cell(node.RowListIndex, ColNames.DelayUnit).Text = node.DelayUnit If node.Params Is Nothing Then Exit Select For i As Integer = 0 To 5 If i < node.Params.Count Then Dim param As AttributeRowNodeTag = node.Params(i) _grd.Cell(node.RowListIndex, ColNames.ParamDesc1 + i * 2).Text = param.Name ' _grd.Cell(node.RowListIndex, ColNames.ParamDesc1 + i * 2).Locked = True If param.Type = AttributeRowNodeTag.DataTypes.List Then _grd.Cell(node.RowListIndex, ColNames.ParamValue1 + i * 2).CellType = CellTypeEnum.ComboBox ElseIf param.Type = AttributeRowNodeTag.DataTypes.Boolean Then _grd.Cell(node.RowListIndex, ColNames.ParamValue1 + i * 2).CellType = CellTypeEnum.CheckBox Else _grd.Cell(node.RowListIndex, ColNames.ParamValue1 + i * 2).CellType = CellTypeEnum.TextBox End If _grd.Cell(node.RowListIndex, ColNames.ParamValue1 + i * 2).Text = param.Value Else _grd.Cell(node.RowListIndex, ColNames.ParamValue1 + i * 2).CellType = CellTypeEnum.TextBox _grd.Cell(node.RowListIndex, ColNames.ParamValue1 + i * 2).Text = "" _grd.Cell(node.RowListIndex, ColNames.ParamDesc1 + i * 2).Text = "" End If Next Case Else End Select End With End Sub ''' ''' 填充表格行的样式 ''' ''' Protected Friend Sub FillRowStyle(node As RowNode) Dim tmpColor As Color Dim tmpFontBold As Boolean Dim tmpCellType As CellTypeEnum Dim tmpCellLocked As Boolean Try With _grd ' .HideGridLines = True .Row(node.RowListIndex).Visible = node.Visible Select Case node.RowType Case RowNode.RowTypeEnum.HotelGroup '1 tmpColor = Color.Black : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White Case RowNode.RowTypeEnum.Hotel '2 tmpColor = Color.Black : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White Case RowNode.RowTypeEnum.HotelRoomType '3 tmpColor = Color.Black : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White Case RowNode.RowTypeEnum.Model '4 tmpColor = Color.DarkViolet : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White Case RowNode.RowTypeEnum.ModelAttributes '5 tmpColor = Color.Green : tmpFontBold = False : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White Case RowNode.RowTypeEnum.ModelAttributeGroup '6 tmpColor = Color.Green : tmpFontBold = False : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White Case RowNode.RowTypeEnum.ModelAttribute '7 tmpColor = Color.Green : tmpFontBold = False : Dim tag As AttributeRowNodeTag = node.Tag : tmpCellLocked = False If tag.Type = AttributeRowNodeTag.DataTypes.List Then tmpCellType = CellTypeEnum.ComboBox Else tmpCellType = CellTypeEnum.TextBox End If .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceGroup '8 tmpColor = Color.FromArgb(0, 0, 240) : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True For i = ColNames.DeviceAlias To ColNames.Max - 1 .Cell(node.RowListIndex, i).BackColor = Color.PowderBlue Next '对象’ Case RowNode.RowTypeEnum.DeviceObject '9 端口 tmpColor = Color.Purple : tmpFontBold = True : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = False For i = ColNames.Node To ColNames.Max - 1 .Cell(node.RowListIndex, i).BackColor = Color.Bisque .Cell(node.RowListIndex, i).Border(EdgeEnum.Top) = LineStyleEnum.Thin .Cell(node.RowListIndex, i).Alignment = AlignmentEnum.LeftCenter .Cell(node.RowListIndex, i).ForeColor = Color.DarkBlue Next 'If _gIsLoading = False Then .Range(node.RowListIndex, ColNames.DeviceMothed, node.RowListIndex, ColNames.ParamValue6).Merge() '’.Cell(node.RowListIndex, ColNames.DeviceName).BackColor = Color.WhiteSmoke .Cell(node.RowListIndex, ColNames.DeviceName).ForeColor = Color.DarkGray '对象属性集合 Case RowNode.RowTypeEnum.DeviceAttributes '10 设备对象属性集合 tmpColor = Color.Green : tmpFontBold = False : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White '对象属性 Case RowNode.RowTypeEnum.DeviceAttribute '13 设备对象属性 tmpColor = Color.Green : tmpFontBold = False : tmpCellLocked = False Dim tag As AttributeRowNodeTag = node.Tag If tag.Type = AttributeRowNodeTag.DataTypes.List Then tmpCellType = CellTypeEnum.ComboBox Else tmpCellType = CellTypeEnum.TextBox End If .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White '设备事件集合 Case RowNode.RowTypeEnum.DeviceEvents '12 tmpColor = Color.DarkBlue : tmpFontBold = False : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White '设备事件 Case RowNode.RowTypeEnum.DeviceEvent '15 tmpColor = Color.DarkBlue : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.Node).BackColor = Color.BlanchedAlmond .Cell(node.RowListIndex, ColNames.DeviceName).BackColor = Color.WhiteSmoke .Cell(node.RowListIndex, ColNames.DeviceName).ForeColor = Color.DarkGray .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White 'Case RowNode.RowTypeEnum.DeviceEventConditionItem '18 ' tmpColor = Color.FromArgb(35, 180, 255) : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True ' .Cell(node.RowListIndex, ColNames.DeviceAlias).ForeColor = tmpColor ' .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White ' .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceEventAllConditions '19 tmpColor = Color.FromArgb(35, 180, 255) : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceEventConditions '20 tmpColor = Color.FromArgb(35, 180, 255) : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = False Dim tag As AttributeRowNodeTag = node.Tag .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceEventActionModeGroup '16 tmpColor = Color.Green : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceEventActionMode '17 tmpColor = Color.Green : tmpFontBold = False : Dim tag As AttributeRowNodeTag = node.Tag : tmpCellLocked = False If tag.Type = AttributeRowNodeTag.DataTypes.List Then tmpCellType = CellTypeEnum.ComboBox Else tmpCellType = CellTypeEnum.TextBox End If .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.ContextualModels '24 tmpColor = Color.Fuchsia : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True '25 场景 Case RowNode.RowTypeEnum.ContextualModel '25 tmpColor = Color.Fuchsia : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.Node).BackColor = Color.BlanchedAlmond .Cell(node.RowListIndex, ColNames.DeviceName).BackColor = Color.WhiteSmoke .Cell(node.RowListIndex, ColNames.DeviceAlias).ForeColor = tmpColor .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceEventAllActions '21 tmpColor = Color.DeepPink : tmpFontBold = True : tmpCellType = CellTypeEnum.TextBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White '22 事件动作组 Case RowNode.RowTypeEnum.DeviceEventActions '22 tmpColor = Color.DeepPink : tmpFontBold = True : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True 'If _gIsLoading = False Then .Range(node.RowListIndex, ColNames.DeviceMothed, node.RowListIndex, ColNames.ParamValue6).Merge() .Cell(node.RowListIndex, ColNames.DeviceMothed).BackColor = Color.LightGray .Cell(node.RowListIndex, ColNames.Node).BackColor = Color.BlanchedAlmond .Cell(node.RowListIndex, ColNames.DeviceAlias).ForeColor = Color.DeepPink .Cell(node.RowListIndex, ColNames.DeviceName).BackColor = Color.LightGray '23 事件动作 Case RowNode.RowTypeEnum.DeviceEventAction '23 tmpColor = Color.Brown : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = False .Cell(node.RowListIndex, ColNames.DeviceAlias).ForeColor = Color.DeepPink 'If _gIsLoading = False Then .Range(node.RowListIndex, ColNames.DeviceAlias, node.RowListIndex, ColNames.ParamValue6).BackColor = Color.White Case RowNode.RowTypeEnum.ExternalModel '26 tmpColor = Color.DarkOrchid : tmpFontBold = True : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.ModelAttributes_XiaoBaoCMD '27 tmpColor = Color.DarkOrchid : tmpFontBold = True : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.Node).BackColor = Color.BlanchedAlmond .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD '28 tmpColor = Color.DarkBlue : tmpFontBold = False : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = False .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White '.Cell(node.RowListIndex, ColNames.DeviceName).CellType = CellTypeEnum.ComboBox Case RowNode.RowTypeEnum.ModelAttributes_DeviceExists '29 tmpColor = Color.DarkSlateGray : tmpFontBold = True : tmpCellType = CellTypeEnum.ComboBox : tmpCellLocked = True .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case RowNode.RowTypeEnum.ModelAttribute_DeviceExists '30 tmpColor = Color.DarkSlateGray : tmpFontBold = False : tmpCellLocked = True Dim tag As AttributeRowNodeTag = node.Tag If tag.Type = AttributeRowNodeTag.DataTypes.List Then tmpCellType = CellTypeEnum.ComboBox Else tmpCellType = CellTypeEnum.TextBox End If .Cell(node.RowListIndex, ColNames.DeviceAlias).BackColor = Color.White .Cell(node.RowListIndex, ColNames.DeviceType).BackColor = Color.White Case Else tmpColor = Color.Black : tmpFontBold = False : tmpCellType = CellTypeEnum.TextBox End Select '.Range(node.RowListIndex, ColNames.DeviceAlias, node.RowListIndex, ColNames.DeviceType).ForeColor = tmpColor '.Range(node.RowListIndex, ColNames.DeviceAlias, node.RowListIndex, ColNames.DeviceType).FontBold = tmpFontBold .Cell(node.RowListIndex, ColNames.Node).ForeColor = tmpColor .Cell(node.RowListIndex, ColNames.Node).FontBold = tmpFontBold .Cell(node.RowListIndex, ColNames.DeviceType).CellType = tmpCellType .Cell(node.RowListIndex, ColNames.DeviceType).Locked = tmpCellLocked .Cell(node.RowListIndex, ColNames.DeviceAlias).FontBold = True .Cell(node.RowListIndex, ColNames.DeviceAlias).FontSize = 9 '如果在错误列表中有此行 If _ruleCheckGobleErrList.ContainsKey(node.RowListIndex) Then Dim errInfo As RuleCheckErrList = _ruleCheckGobleErrList(node.RowListIndex) Select Case errInfo.err_errType Case RuleCheckErrTypeEnum.RuleCheck_OK .Cell(node.RowListIndex, errInfo.err_col).BackColor = Color.White Case RuleCheckErrTypeEnum.RuleCheck_Warning .Cell(node.RowListIndex, errInfo.err_col).BackColor = Color.Yellow .Cell(node.RowListIndex, errInfo.err_col).ForeColor = Color.Black Case RuleCheckErrTypeEnum.RuleCheck_Error .Cell(node.RowListIndex, errInfo.err_col).BackColor = Color.Salmon .Cell(node.RowListIndex, errInfo.err_col).ForeColor = Color.Black Case Else End Select End If If node.Compile Then ' .Cell(node.RowListIndex, ColNames.DeviceAlias).ForeColor = Color.Black .Cell(node.RowListIndex, ColNames.DeviceAlias).ForeColor = .Cell(node.RowListIndex, ColNames.Node).ForeColor For i = ColNames.DeviceType To ColNames.Max - 1 .Cell(node.RowListIndex, i).ForeColor = Color.Black Next Else For i = ColNames.DeviceAlias To ColNames.Max - 1 .Cell(node.RowListIndex, i).ForeColor = Color.Gray Next End If End With Catch ex As Exception MsgBox("FillRowStyly Error: " & vbCrLf & "行号:" & node.RowListIndex & vbCrLf & ex.Message) End Try End Sub Private _gIsFristMergeCell As Boolean = True Public Sub MergeCell() If _gIsLoading = True Then Return If _gIsFristMergeCell = False Then Return LockGridAutoRedraw() SkipCellChange = True '先全部展开 'ExpandRows(_rootNode) _rootNode.ExpandAll() For Each node As RowNode In _rootNode.RowList Select Case node.RowType Case RowNode.RowTypeEnum.DeviceObject '9 端口 , If _gIsLoading = False Then _grd.Range(node.RowListIndex, ColNames.DeviceMothed, node.RowListIndex, ColNames.ParamValue6).Merge() Case RowNode.RowTypeEnum.DeviceEventAction '23 If _gIsLoading = False Then _grd.Range(node.RowListIndex, ColNames.DeviceAlias, node.RowListIndex, ColNames.ParamValue6).BackColor = Color.White Case RowNode.RowTypeEnum.DeviceEventActions '22 If _gIsLoading = False Then _grd.Range(node.RowListIndex, ColNames.DeviceMothed, node.RowListIndex, ColNames.ParamValue6).Merge() End Select '更新格式’ 'FillRowStyle(node) Next _gIsFristMergeCell = False SkipCellChange = False UnLockGridAutoRedraw() End Sub #End Region #Region "表格RCU模型更新" ''' ''' 选择路径后更新基类 ''' ''' 基类文件完整路径 ''' 更新类型是否为外接设备 Public Sub UpdateRCUModel(DirPath As String, filePath As String, Optional isInterval As Boolean = False) If IO.File.Exists(filePath) = False Then Throw New Exception($"未查询到路径{filePath}") '模型加载 Dim a As DeviceModel = BXmlSerializer.DeserializeFormXml(Of DeviceModel)(filePath) LockGridAutoRedraw() SkipCellChange = True For i = 0 To _grd.Rows - 1 Dim node As RowNode = _rootNode.RowList(i) Select Case node.RowType Case RowNode.RowTypeEnum.Model '更新模型节点(有且只有一个模型对象) If isInterval Then Continue For If a.Name <> node.Name Then Continue For UpdateModel(node, a) '更新模型对象 Dim classPath As String = $"{DirPath}\Data\Model\BaseModel\{a.Desc.DevBasicClassFilename}" UpdateBaseClass(classPath) '更新条件模型 Dim conditionPath As String = $"{DirPath}\Data\Model\BaseModel\{a.Desc.DevCondictionFilename}" UpdateCondition(conditionPath) Exit For Case RowNode.RowTypeEnum.ExternalModel '更新多个外接设备节点(可以出现多个相同类型的外接设备模型) If isInterval = False Then Continue For If a.Name <> node.Name Then Continue For UpdateModel(node, a, isInterval) End Select Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 更新模型节点内容 ''' ''' 模型节点 ''' 主机模型 ''' 是否为外接模型 Private Sub UpdateModel(modelNode As RowNode, model As DeviceModel, Optional isInterval As Boolean = False) Dim tipStr As String If isInterval Then tipStr = "外设" Else tipStr = "主机" End If modelNode.Name = model.Name modelNode.Text = $"{tipStr}:{model.Name}" modelNode.Tag = New ModelRowNodeTag With {.Desc = model.Desc} '记录被移除的节点 Dim srcDeviceNodes As New List(Of RowNode) Dim srcAttrNodes As New List(Of RowNode) For Each node As RowNode In modelNode.Nodes Select Case node.RowType Case RowNode.RowTypeEnum.ModelAttributes For Each attNode As RowNode In node.Nodes If attNode.RowType <> RowNode.RowTypeEnum.ModelAttributeGroup Then Continue For srcAttrNodes.Add(attNode) Next Case RowNode.RowTypeEnum.DeviceGroup srcDeviceNodes.Add(node) End Select Next '移除所有模型下节点 RemoveNodeChildRow(modelNode) '填充主机属性 Dim configNode As New RowNode configNode.RowType = RowNode.RowTypeEnum.ModelAttributes configNode.Name = $"{tipStr}属性集合" configNode.Text = $"{tipStr}属性" modelNode.AddNode(configNode) '更新属性组 UpdateModelAttributeGroup(configNode, model, srcAttrNodes) '更新对象组 UpdateDeviceGroup(modelNode, model, srcDeviceNodes) '填充数据行 AddNodeChildRow(modelNode, True) End Sub ''' ''' 更新模型设备组节点 ''' ''' 主机模型节点 ''' 主机模型 ''' 被移除的原设备组节点集合 Private Sub UpdateDeviceGroup(pNode As RowNode, model As DeviceModel, srcDeviceNodes As List(Of RowNode)) If model.Nodes Is Nothing Then Return For Each group As DeviceChildNodeClass In model.Nodes Dim groupNode As New RowNode groupNode.RowType = RowNode.RowTypeEnum.DeviceGroup groupNode.Name = $"{group.Name}" groupNode.Text = "设备组:" & group.Name ' groupNode.Tag = group pNode.AddNode(groupNode) Dim srcGroupNode As RowNode = srcDeviceNodes.Find(Function(p As RowNode) Return p.Name = groupNode.Name End Function) If group.Nodes Is Nothing Then Continue For For Each dev As DeviceChildNode In group.Nodes Dim deviceNode As RowNode If srcGroupNode IsNot Nothing Then groupNode.DeviceAlias = srcGroupNode.DeviceAlias deviceNode = AppendDeviceObjectNode(dev, False) For Each srcNode As RowNode In srcGroupNode.Nodes 'todo:被移除的设备对象与被移除的对象组处理 If srcNode.Name <> deviceNode.Name Then Continue For deviceNode.DeviceAlias = srcNode.DeviceAlias If String.IsNullOrEmpty(srcNode.DeviceType) Then If dev.DefaultClass IsNot Nothing AndAlso String.IsNullOrEmpty(dev.DefaultClass) = False Then deviceNode.DeviceType = dev.DefaultClass '添加子节点 FillDeviceObjectNode(deviceNode) Else '添加RS485设备下所有子节点 If dev.Interface = "RS485Active" OrElse dev.Interface = "RS485Polling" Then For Each n As RowNode In srcNode.Nodes deviceNode.AddNode(n) Next End If End If Else deviceNode.DeviceType = srcNode.DeviceType For Each node As RowNode In srcNode.Nodes deviceNode.AddNode(node) Next End If Next Else deviceNode = AppendDeviceObjectNode(dev) End If groupNode.AddNode(deviceNode) Next Next End Sub ''' ''' 更新模型属性组节点 ''' ''' 主机模型节点 ''' 主机模型 ''' 被移除的原属性组节点集合 Private Sub UpdateModelAttributeGroup(pNode As RowNode, model As DeviceModel, srcAttrNodes As List(Of RowNode)) Dim ConfigGroup_CfgType As RowNode.CfgTypeEnum If model.Config IsNot Nothing Then For Each group As DeviceModelConfigGroup In model.Config Dim groupNode As RowNode = AppendDeviceModelAttributeGroupNode(group) pNode.AddNode(groupNode) Dim srcGroupNode As RowNode = srcAttrNodes.Find(Function(p As RowNode) Return p.Name = groupNode.Name End Function) Select Case group.CFG_Type Case "XiaoBaoCMD" ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_XiaoBaoCMD Case "DeviceExists" ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_DeviceExists Case "Default" ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_Default Case Else ConfigGroup_CfgType = RowNode.CfgTypeEnum.CfgType_Default End Select For Each config As DeviceChildNodeAttribute In group.Attributes Dim attrNode As RowNode = AppendDeviceModelAttributeNode(config, ConfigGroup_CfgType, group.CFG_Value) groupNode.AddNode(attrNode) '填充之前对应属性节点值 If srcGroupNode Is Nothing Then Continue For For Each node As RowNode In srcGroupNode.Nodes If node.Name <> attrNode.Name Then Continue For Dim tag As AttributeRowNodeTag = attrNode.Tag '’Console.WriteLine($"Node Index:{node.RowListIndex} Name:{node.Name} Vale:{node.DeviceType}") '填充属性值 If tag.IsRange(node.DeviceType) Then tag.Value = node.DeviceType attrNode.DeviceType = node.DeviceType End If Exit For Next Next Next End If End Sub #End Region #Region "表格事件模型更新" Public Sub UpdateCondition(filePath As String) If IO.File.Exists(filePath) = False Then Throw New Exception($"未查询到路径{filePath}") '模型加载 Dim a As ConfigActionConcitons = BXmlSerializer.DeserializeFormXml(Of ConfigActionConcitons)(filePath) Condictions = a ConditionFileName = IO.Path.GetFileName(filePath) LockGridAutoRedraw() SkipCellChange = True For i = 0 To _grd.Rows - 1 Dim node As RowNode = _rootNode.RowList(i) Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventActionModeGroup '更新事件执行方式 UpdateExecMode(node, a) Case RowNode.RowTypeEnum.DeviceEventAllConditions '更新执行条件 UpdateExecCondition(node, a) End Select Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 更新执行方式(与节点TAG为属性类型的变量处理方式有相似点,考虑整合封装) ''' ''' Private Sub UpdateExecMode(groupNode As RowNode, dest As ConfigActionConcitons) '记录被移除的节点 Dim srcAttNodes As New List(Of RowNode) For Each srcAttNode As RowNode In groupNode.Nodes srcAttNodes.Add(srcAttNode) Next '移除所有属性节点 RemoveNodeChildRow(groupNode) '添加基类的属性节点 For Each att As Conction In dest.ExeMode Dim attNode As RowNode = AppendActionMode(att) Dim tag As AttributeRowNodeTag = attNode.Tag '填充属性值 Dim srcNode As RowNode = srcAttNodes.Find(Function(p As RowNode) Return p.Name = attNode.Name End Function) If srcNode IsNot Nothing AndAlso tag.IsRange(srcNode.DeviceType) Then tag.Value = srcNode.DeviceType attNode.DeviceType = srcNode.DeviceType End If groupNode.AddNode(attNode) Next '填充属性组节点 AddNodeChildRow(groupNode, True) End Sub ''' ''' 更新执行条件 ''' ''' Private Sub UpdateExecCondition(groupNode As RowNode, dest As ConfigActionConcitons) '记录被移除的节点 Dim srcAttNodes As New List(Of RowNode) For Each srcAttNode As RowNode In groupNode.Nodes srcAttNodes.Add(srcAttNode) Next '移除所有属性节点 RemoveNodeChildRow(groupNode) '添加基类的属性节点 For Each att As Conction In dest.Conction Dim attNode As RowNode = AppendActionCondition(att) Dim tag As AttributeRowNodeTag = attNode.Tag '填充属性值 Dim srcNode As RowNode = srcAttNodes.Find(Function(p As RowNode) Return p.Name = attNode.Name End Function) If srcNode IsNot Nothing AndAlso tag.IsRange(srcNode.DeviceType) Then tag.Value = srcNode.DeviceType attNode.DeviceType = srcNode.DeviceType End If groupNode.AddNode(attNode) Next '填充属性组节点 AddNodeChildRow(groupNode, True) End Sub #End Region #Region "表格基类模型更新" ''' ''' 选择路径后更新基类 ''' ''' 基类文件完整路径 Public Sub UpdateBaseClass(filePath As String) If IO.File.Exists(filePath) = False Then Throw New Exception($"未查询到路径{filePath}") '模型加载 Dim a As DeviceObjectClasses = BXmlSerializer.DeserializeFormXml(Of DeviceObjectClasses)(filePath) BasicClasses = a BasicClassFilename = IO.Path.GetFileName(filePath) '更新对象节点属性与事件 UpdateDeviceObjectBaseClass(a) '更新动作节点函数 UpdateObjectAction(a) End Sub ''' ''' 更新设备基类信息属性与事件 ''' ''' Private Sub UpdateDeviceObjectBaseClass(dest As DeviceObjectClasses) LockGridAutoRedraw() SkipCellChange = True Dim destsFiled As New Dictionary(Of String, DeviceObjectType) '获取所有基类 For Each destClass As DeviceObjectType In dest.DeviceClass destsFiled.Add(destClass.Name, destClass) Next For i = 0 To _grd.Rows - 1 Dim node As RowNode = _rootNode.RowList(i) If node.RowType <> RowNode.RowTypeEnum.DeviceObject Then Continue For If String.IsNullOrEmpty(node.DeviceType) Then Continue For '更新设备对象设备类型 If String.IsNullOrEmpty(node.DeviceType) Then Continue For If destsFiled.ContainsKey(node.DeviceType) Then '处理已存在的基类 '更新属性 UpdateObjectAttributes(node, destsFiled(node.DeviceType)) '更新事件 UpdateObjectEvents(node, destsFiled(node.DeviceType)) FillRowStyle(node) FillRowText(node) Else '处理被删除的设备类型 '移除设备节点下所有节点 RemoveNodeChildRow(node) ' 重置设备类型 node.DeviceType = "" FillRowStyle(node) FillRowText(node) End If Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 更新设备对象属性组节点 ''' ''' 设备对象节点 ''' 设备对象类型 Public Sub UpdateObjectAttributes(objectNode As RowNode, objectType As DeviceObjectType) For Each groupNode As RowNode In objectNode.Nodes If groupNode.RowType <> RowNode.RowTypeEnum.DeviceAttributes Then Continue For Dim srcAttNodes As New List(Of RowNode) For Each srcAttNode As RowNode In groupNode.Nodes srcAttNodes.Add(srcAttNode) Next '移除所有属性节点 RemoveNodeChildRow(groupNode) '添加基类的属性节点 For Each att As DeviceChildNodeAttribute In objectType.Attributes Dim attNode As RowNode = AppendObjectAttribute(att) Dim tag As AttributeRowNodeTag = attNode.Tag '填充属性值 Dim srcNode As RowNode = srcAttNodes.Find(Function(p As RowNode) Return p.Name = attNode.Name End Function) If srcNode IsNot Nothing AndAlso tag.IsRange(srcNode.DeviceType) Then tag.Value = srcNode.DeviceType attNode.DeviceType = srcNode.DeviceType attNode.DeviceAlias = srcNode.DeviceAlias End If groupNode.AddNode(attNode) Next '填充属性组节点 AddNodeChildRow(groupNode, True) Next End Sub ''' ''' 更新设备事件集合 ''' ''' 设备对象节点 ''' 设备类型模型 Public Sub UpdateObjectEvents(objectNode As RowNode, objectType As DeviceObjectType) For Each groupNode As RowNode In objectNode.Nodes If groupNode.RowType <> RowNode.RowTypeEnum.DeviceEvents Then Continue For Dim srcAttNodes As New List(Of RowNode) For Each srcAttNode As RowNode In groupNode.Nodes srcAttNodes.Add(srcAttNode) Next '移除所有子节点 RemoveNodeChildRow(groupNode) '添加基类的事件节点 For Each att As DeviceChildNodeEvent In objectType.Events Dim attNode As RowNode = AppendObjectEvent(att, False) '填充事件下节点 Dim srcNode As RowNode = srcAttNodes.Find(Function(p As RowNode) Return p.Name = attNode.Name End Function) If srcNode IsNot Nothing Then attNode.DeviceAlias = srcNode.DeviceAlias For Each node As RowNode In srcNode.Nodes attNode.AddNode(node) Next Else attNode.AddNode(CreateRowNode(RowNode.RowTypeEnum.DeviceEventConditionItem)) End If groupNode.AddNode(attNode) Next '填充事件组节点 AddNodeChildRow(groupNode, True) Next End Sub ''' ''' 更新设备动作 ''' ''' Public Sub UpdateObjectAction(dest As DeviceObjectClasses) LockGridAutoRedraw() SkipCellChange = True Dim destsFiled As New Dictionary(Of String, DeviceObjectType) '获取所有基类 For Each destClass As DeviceObjectType In dest.DeviceClass destsFiled.Add(destClass.Name, destClass) Next For Each node As RowNode In _rootNode.RowList If node.RowType <> RowNode.RowTypeEnum.DeviceEventAction Then Continue For If String.IsNullOrEmpty(node.DeviceType) Then Continue For If String.IsNullOrEmpty(node.DeviceMothed) Then Continue For If destsFiled.ContainsKey(node.DeviceType) Then '对比函数 Dim m As DeviceObjectType = destsFiled(node.DeviceType) Dim index As Integer = m.Methods.FindIndex(Function(p As DeviceChildNodeMethod) Return p.Name = node.DeviceMothed End Function) If index >= 0 Then '已有的函数 Dim method As DeviceChildNodeMethod = m.Methods(index) '对比参数 Dim params As New List(Of AttributeRowNodeTag) For Each p As AttributeRowNodeTag In node.Params params.Add(p) Next node.Params.Clear() '填充参数 For i As Integer = 0 To method.Params.Count - 1 Dim param As New AttributeRowNodeTag(method.Params(i).Name, method.Params(i).DataType, method.Params(i).DataRange, method.Params(i).DataRangeValue, method.Params(i).Desc, method.Params(i).DataDefault) '填充参数值 Dim srcParam As AttributeRowNodeTag = params.Find(Function(p As AttributeRowNodeTag) Return p.Name = param.Name End Function) If srcParam IsNot Nothing AndAlso param.IsRange(srcParam.Value) Then param.Value = srcParam.Value End If node.Params.Add(param) Next FillRowStyle(node) FillRowText(node) Else '移除的函数 node.DeviceMothed = "" node.DeviceName = "" node.Params.Clear() FillRowStyle(node) FillRowText(node) End If Else '清空函数 node.DeviceType = "" node.DeviceMothed = "" node.DeviceName = "" node.Params.Clear() FillRowStyle(node) FillRowText(node) End If Next SkipCellChange = False UnLockGridAutoRedraw() End Sub #End Region #Region "TreeView 事件" ''' ''' treeview 双击事件,双击后导航至表格对应的节点 ''' ''' ''' Private Sub Tv_DoubleClick(sender As Object, e As EventArgs) If _tv.SelectedNode.Level < 2 Then Return Dim tmpSelectedNode As rsmTreeNode = CType(_tv.SelectedNode, rsmTreeNode) Dim tmpIdx As Integer = tmpSelectedNode.rowNodeIdx Dim tmpRowNode As RowNode = FindRowNode(tmpIdx) LockGridAutoRedraw() SkipCellChange = True '展开节点的所有直系父节点,一直追溯到0级 SetRowFamilyExpand(tmpRowNode) '指定节点的单元格获取焦点 _grd.Cell(tmpIdx, 2).SetFocus() _grd.Range(tmpIdx, ColNames.DeviceAlias, tmpIdx, ColNames.DelayUnit).SelectCells() '重新整表刷新格式 For Each node As RowNode In _rootNode.RowList FillRowStyle(node) Next '隐藏属性 SetRowsVisible(RowNode.RowTypeEnum.DeviceAttribute, False) '隐藏执行条件 SetRowsVisible(RowNode.RowTypeEnum.DeviceEventAllConditions, False) SkipCellChange = False UnLockGridAutoRedraw() End Sub #End Region #Region "表格事件" 'Private Sub GrdEvent_LeaveCell(Sender As Object, e As Grid.LeaveCellEventArgs) Handles GrdEvent.LeaveCell 'End Sub 'Private Sub GrdEvent_MouseUp(Sender As Object, e As MouseEventArgs) Handles GrdEvent.MouseUp ' Console.WriteLine("mouse up") 'End Sub 'Private Sub GrdEvent_MouseDown(Sender As Object, e As MouseEventArgs) Handles GrdEvent.MouseDown ' Console.WriteLine("mouse down") 'End Sub Private Sub Grid_MouseUp(Sender As Object, e As MouseEventArgs) _isCellLeave_push = False '不允许cell leave时对位置压栈 End Sub Private Sub Grid_MouseDown(Sender As Object, e As MouseEventArgs) _isCellLeave_push = True '允许cell leave时对位置压栈 End Sub ''' ''' 当前活动单元格变更到一个不同的单元格之前立即发生。 ''' Row 返回一个Integer值,标识单元格变更之前的行号。 ''' Col 返回一个Integer值, 标识单元格变更之前的列号。 ''' NewRow 返回或设置一个Integer值, 标识单元格变更之后的行号。NewRow属性的值可以改变,使活动单元格移动到此行。 ''' NewCol 返回或设置一个Integer值, 标识单元格变更之后的列号。NewCol属性的值可以改变,使活动单元格移动到此列。 ''' Cancel 设置一个Boolean值, 将Cancel属性设置为True, 可以防止活动单元格离开原来的位置。 ''' ''' ''' Private Sub Grid_LeaveCell(Sender As Object, e As Grid.LeaveCellEventArgs) If _isCellLeave_push = True Then Dim tmpCellLocation As GridCellLocation tmpCellLocation.row = e.Row tmpCellLocation.col = e.Col stCellNav_Next.Push(tmpCellLocation) '向前导航压栈 End If End Sub ''' ''' 表格下拉框点击事件 ''' ''' ''' Private Sub Grid_ComboClick(Sender As Object, e As Grid.ComboClickEventArgs) _skipMouseMoveChange = False End Sub ''' ''' 表格绘制事件 ''' ''' ''' Private Sub Grid_OwnerDrawCell(Sender As Object, e As FlexCell.Grid.OwnerDrawCellEventArgs) If e.Row < _drawRow OrElse e.Col <> _drawCol Then Return Dim i, j As Integer Dim blnDrawLine As Boolean Dim node, tmpNode As RowNode Dim intLevel As Integer Dim intWidth As Integer Dim intAdd As Integer If ShowNodeIcon Then intWidth = 20 intAdd = 26 Else intWidth = 10 intAdd = 6 End If If e.Row - _drawRow + 1 >= _rootNode.RowList.Count Then Return node = _rootNode.RowList(e.Row - _drawRow + 1) If node Is Nothing Then Return intLevel = node.Lever - 1 '画树线 Dim pen As New System.Drawing.Pen(Color.CornflowerBlue, 1) Try pen.DashStyle = Drawing2D.DashStyle.Solid For i = 0 To intLevel If i < intLevel - 1 Then blnDrawLine = True tmpNode = node For j = i To intLevel - 2 tmpNode = tmpNode.ParentNode Next If tmpNode.NextNode Is Nothing Then blnDrawLine = False End If If blnDrawLine Then '全部 e.Graphics.DrawLine(pen, CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Top - 1), CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Bottom + 1)) End If ElseIf i = intLevel - 1 Then '上半部分 e.Graphics.DrawLine(pen, CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Top - 1), CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Top + e.Bounds.Height / 2)) If node.NextNode IsNot Nothing Then '下半部分 e.Graphics.DrawLine(pen, CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Top + e.Bounds.Height / 2), CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Bottom + 1)) End If ElseIf i = intLevel Then '下半部分 If node.VisibleNodesCount >= 1 Then ' If node.Expanded AndAlso node.Count > 0 Then If ShowNodeIcon Then e.Graphics.DrawLine(pen, CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Top + e.Bounds.Height / 2) + 7, CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Bottom + 1)) Else e.Graphics.DrawLine(pen, CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Top + e.Bounds.Height / 2), CInt(e.Bounds.Left + intWidth * i + intAdd), CInt(e.Bounds.Bottom + 1)) End If End If End If '水平的 If intLevel > 0 Then e.Graphics.DrawLine(pen, CInt(e.Bounds.Left + intWidth * (intLevel - 1) + intAdd), CInt(e.Bounds.Top + e.Bounds.Height / 2), CInt(e.Bounds.Left + intWidth * (intLevel - 1) + intAdd + 10), CInt(e.Bounds.Top + e.Bounds.Height / 2)) End If Next pen.Dispose() '+/- If node.Count > 0 Then Dim rect As New Rectangle(e.Bounds.Left + 2 + intLevel * intWidth, CInt(e.Bounds.Top + (e.Bounds.Height - 9) / 2), 8, 8) e.Graphics.FillRectangle(Brushes.White, rect) e.Graphics.DrawRectangle(Pens.Black, rect) If node.Expanded Then e.Graphics.DrawLine(Pens.Black, rect.Left + 2, rect.Top + 4, rect.Right - 2, rect.Top + 4) Else e.Graphics.DrawLine(Pens.Black, rect.Left + 2, rect.Top + 4, rect.Right - 2, rect.Top + 4) e.Graphics.DrawLine(Pens.Black, rect.Left + 4, rect.Top + 2, rect.Left + 4, rect.Bottom - 2) End If End If '图标 'If _showNodeIcon Then ' If node.ChildrenCount > 0 Then ' DrawIconEx(e.hDC, e.Bounds.Left + intWidth * intLevel + 18, e.Bounds.Top + (e.Bounds.Height - 16) / 2, m_FolderIcon.Handle, 16, 16, 0, 0, DI_NORMAL) ' Else ' DrawIconEx(e.hDC, e.Bounds.Left + intWidth * intLevel + 18, e.Bounds.Top + (e.Bounds.Height - 16) / 2, m_FileIcon.Handle, 16, 16, 0, 0, DI_NORMAL) ' End If 'End If '文字 Dim bColor As New SolidBrush(_grd.Cell(e.Row, e.Col).ForeColor) If bColor.Color.A = 0 Then bColor.Color = Color.Black With _grd.Cell(e.Row, e.Col) If ShowNodeIcon Then e.Graphics.DrawString(.Text, .Font, bColor, e.Bounds.Left + intWidth * intLevel + 35, e.Bounds.Top + (e.Bounds.Height - e.Graphics.MeasureString(.Text, .Font).Height) / 2 + 1) Else e.Graphics.DrawString(.Text, .Font, bColor, e.Bounds.Left + intWidth * intLevel + 12, e.Bounds.Top + (e.Bounds.Height - e.Graphics.MeasureString(.Text, .Font).Height) / 2 + 1) End If End With Catch ex As Exception End Try e.Handled = True End Sub ''' ''' 表格按键松开事件 ''' ''' ''' Private Sub Grid_KeyUp(sender As Object, e As KeyEventArgs) _flgControl = e.Modifiers = Keys.Control End Sub ''' ''' 表格按键按下事件 ''' ''' ''' Private Sub Grid_KeyDown(sender As Object, e As KeyEventArgs) _flgControl = e.Modifiers = Keys.Control If e.Modifiers = Keys.Control AndAlso e.KeyCode = Keys.V Then e.Handled = True PasteRows() ElseIf e.Modifiers = Keys.Control AndAlso e.KeyCode = Keys.C Then e.Handled = True CopyRows() ElseIf e.Modifiers = Keys.Control AndAlso e.KeyCode = Keys.X Then e.Handled = True CutRows() ElseIf e.Modifiers = Keys.Control AndAlso e.KeyCode = Keys.Z Then Undo() ElseIf e.Modifiers = Keys.Control AndAlso e.KeyCode = Keys.Y Then Redo() ElseIf e.Modifiers = Keys.Control AndAlso e.KeyCode = Keys.D0 Then Zoom(1) End If End Sub ''' ''' 表格点击事件 ''' ''' ''' Private Sub Grid_Click(sender As Object, e As EventArgs) If _grd.EditorVisible Then Return '处于编辑状态 Try Dim point As Point = _grd.PointToClient(System.Windows.Forms.Cursor.Position) Dim cel As Cell = _grd.HitTest(point.X, point.Y) If cel Is Nothing Then Return rsmTreeViewSelectItem(cel.Row) If cel.Row < _drawRow OrElse cel.Col <> _drawCol Then Return If _rootNode Is Nothing Then Return Dim node As RowNode = _rootNode.RowList(cel.Row - _drawRow + 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.Lever - 1) * intWidth, cel.Bounds.Top + ((cel.Bounds.Height - 9) \ 2), 8, 8) If rect.Contains(point) = False Then Return If node.Expanded Then LockGridAutoRedraw() CollapseRows(node) UnLockGridAutoRedraw() Else LockGridAutoRedraw() ExpandRows(node) UnLockGridAutoRedraw() End If Catch ex As Exception Console.WriteLine($"Grid_Click Error:{ex.Message}") End Try End Sub ''' ''' 表格双击事件 ''' ''' ''' Private Sub Grid_DoubleClick(Sender As Object, e As EventArgs) If _grd.EditorVisible Then Return '处于编辑状态 If _flgControl Then _zoomNum = 1 : Zoom(_zoomNum) '还原 Try Dim point As Point = _grd.PointToClient(System.Windows.Forms.Cursor.Position) Dim cel As Cell = _grd.HitTest(point.X, point.Y) If cel Is Nothing Then Return If cel.Row < _drawRow OrElse cel.Col <> _drawCol Then Return If _rootNode Is Nothing Then Return Dim node As RowNode = _rootNode.RowList(cel.Row - _drawRow + 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.Lever - 1) * intWidth, cel.Bounds.Top + ((cel.Bounds.Height - 9) \ 2), 8, 8) If rect.Contains(point) Then Return LockGridAutoRedraw() If node.Expanded Then CollapseRows(node) Else ExpandRows(node) End If UnLockGridAutoRedraw() Catch ex As Exception Console.WriteLine($"Grid_DoubleClick Error:{ex.Message}") End Try End Sub ''' ''' 表格选择内容改变事件 ''' ''' ''' Private Sub Grid_SelChange(Sender As Object, e As FlexCell.Grid.SelChangeEventArgs) Static lastRow As Integer = 0 Static lastCol As Integer = 0 Dim row As Integer = e.FirstRow If row < _drawRow Then Return If e.FirstRow = lastRow AndAlso e.FirstCol = lastCol Then Return Dim node As RowNode = FindRowNode(row) If node Is Nothing Then Return LockGridAutoRedraw() With _grd Select Case node.RowType Case RowNode.RowTypeEnum.ModelAttribute .Cell(0, ColNames.DeviceType).Text = "模型属性" .Range(0, ColNames.Action, 0, ColNames.DeviceType).ForeColor = Color.Green .Range(0, ColNames.DeviceType + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray Case RowNode.RowTypeEnum.DeviceObject _grd.Cell(0, ColNames.DeviceType).Text = EnumExtender.GetEnumDescription(ColNames.DeviceType) _grd.Cell(0, ColNames.DeviceName).Text = EnumExtender.GetEnumDescription(ColNames.DeviceName) _grd.Cell(0, ColNames.DeviceMothed).Text = EnumExtender.GetEnumDescription(ColNames.DeviceMothed) .Range(0, ColNames.Action, 0, ColNames.DeviceType).ForeColor = Color.Green .Range(0, ColNames.DeviceType + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray Case RowNode.RowTypeEnum.DeviceAttribute _grd.Cell(0, ColNames.DeviceType).Text = "设备属性" .Range(0, ColNames.Action, 0, ColNames.DeviceType).ForeColor = Color.Green .Range(0, ColNames.DeviceType + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray Case RowNode.RowTypeEnum.DeviceEventConditions _grd.Cell(0, ColNames.DeviceType).Text = "条件参数" .Range(0, ColNames.Action, 0, ColNames.DeviceMothed).ForeColor = Color.Green .Range(0, ColNames.DeviceMothed + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray Case RowNode.RowTypeEnum.DeviceEventActionMode _grd.Cell(0, ColNames.DeviceType).Text = "执行方式" .Range(0, ColNames.Action, 0, ColNames.DeviceMothed).ForeColor = Color.Green .Range(0, ColNames.DeviceMothed + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray Case RowNode.RowTypeEnum.DeviceEventAction _grd.Cell(0, ColNames.DeviceType).Text = EnumExtender.GetEnumDescription(ColNames.DeviceType) _grd.Cell(0, ColNames.DeviceName).Text = EnumExtender.GetEnumDescription(ColNames.DeviceName) _grd.Cell(0, ColNames.DeviceMothed).Text = EnumExtender.GetEnumDescription(ColNames.DeviceMothed) .Range(0, ColNames.Action, 0, ColNames.Max - 1).ForeColor = Color.Green '.Range(0, ColNames.Mothed + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray Case Else _grd.Cell(0, ColNames.DeviceType).Text = EnumExtender.GetEnumDescription(ColNames.DeviceType) _grd.Cell(0, ColNames.DeviceName).Text = EnumExtender.GetEnumDescription(ColNames.DeviceName) _grd.Cell(0, ColNames.DeviceMothed).Text = EnumExtender.GetEnumDescription(ColNames.DeviceMothed) .Range(0, ColNames.Action, 0, ColNames.Node).ForeColor = Color.Green .Range(0, ColNames.Node + 1, 0, ColNames.Max - 1).ForeColor = Color.Gray End Select End With UnLockGridAutoRedraw() RaiseEvent TipChanged(_grd, FillTipString(e.FirstCol, node)) lastRow = e.FirstRow lastCol = e.FirstCol End Sub ''' ''' 表格下拉框显示事件 ''' ''' ''' Private Sub Grid_ComboDropDown(Sender As Object, e As FlexCell.Grid.ComboDropDownEventArgs) Dim node As RowNode = FindRowNode(e.Row) If node Is Nothing Then Return _skipMouseMoveChange = True Select Case e.Col Case ColNames.DeviceType _grd.ComboBox(0).Items.Clear() Select Case node.RowType Case RowNode.RowTypeEnum.ModelAttribute '模型参数 '添加类型 Dim tag As AttributeRowNodeTag = node.Tag _grd.ComboBox(0).Items.AddRange(tag.GetRangeArray) Case RowNode.RowTypeEnum.ModelAttribute_DeviceExists '设备存在参数 '添加类型 Dim tag As AttributeRowNodeTag = node.Tag _grd.ComboBox(0).Items.AddRange(tag.GetRangeArray) Case RowNode.RowTypeEnum.DeviceAttribute '设备对象参数 Dim tag As AttributeRowNodeTag = node.Tag _grd.ComboBox(0).Items.AddRange(tag.GetRangeArray) Case RowNode.RowTypeEnum.DeviceObject '设备对象 '添加类型 Dim tag As DeviceObjectRowNodeTag = node.Tag For Each bc As BaseClass In tag.Device.BaseClasses.Classes _grd.ComboBox(0).Items.Add(bc.Name) Next Case RowNode.RowTypeEnum.DeviceEventConditions '添加执行条件 Dim tag As AttributeRowNodeTag = node.Tag _grd.ComboBox(0).Items.AddRange(tag.GetRangeArray) Case RowNode.RowTypeEnum.DeviceEventActionMode '添加执行方式 Dim tag As AttributeRowNodeTag = node.Tag _grd.ComboBox(0).Items.AddRange(tag.GetRangeArray) Case RowNode.RowTypeEnum.DeviceEventAction '设备事件动作 '添加已有设备类型 _grd.ComboBox(0).Items.AddRange(_usedDevTypes.GetAllDeviceTypes(UsedDeviceTypes.GetsEnum.Action)) Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD '小宝命令集 _grd.ComboBox(0).Items.AddRange(_usedDevTypes.GetAllDeviceTypes(UsedDeviceTypes.GetsEnum.Xiaobao)) End Select Case ColNames.DeviceName '名称 _grd.ComboBox(ColNames.DeviceName).Items.Clear() Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction, RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD '小宝命令集 '添加对应类型的设备名称 Dim type As String = _grd.Cell(e.Row, ColNames.DeviceType).Text If String.IsNullOrEmpty(type) Then Return For Each r As RowNode In _usedDevTypes.GetRowNodes(type) If String.IsNullOrEmpty(r.DeviceAlias) Then Continue For _grd.ComboBox(ColNames.DeviceName).Items.Add(r.DeviceAlias) Next End Select Case ColNames.DeviceMothed '方法 _grd.ComboBox(ColNames.DeviceMothed).Items.Clear() Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction '添加对应类型的设备方法 Dim type As String = _grd.Cell(e.Row, ColNames.DeviceType).Text If String.IsNullOrEmpty(type) Then Return Dim cs As DeviceObjectType = BasicClasses.FindDeviceClass(type) If cs Is Nothing Then Return For Each method As DeviceChildNodeMethod In cs.Methods _grd.ComboBox(ColNames.DeviceMothed).Items.Add(method.Name) Next End Select Case ColNames.ParamValue1, ColNames.ParamValue2, ColNames.ParamValue3, ColNames.ParamValue4, ColNames.ParamValue5, ColNames.ParamValue6 '参数值 Dim index As Integer = (e.Col - ColNames.ParamValue1) \ 2 If node.Params.Count <= index Then Return _grd.ComboBox(0).Items.Clear() _grd.ComboBox(0).Items.AddRange(node.Params(index).GetRangeArray) Case Else Console.WriteLine($"Grid_ComboDropDown without Col:{e.Col}") End Select End Sub ''' ''' 表格单元格内容改变事件 ''' ''' ''' Private Sub Grid_CellChange(Sender As Object, e As FlexCell.Grid.CellChangeEventArgs) If e.Row < _drawRow Then Return If SkipCellChange Then Return _isCellChanged = True SkipCellChange = True _undoManager.RunCommand(New TextChangedCommand(Me, e.Row, e.Col, _grd.Cell(e.Row, e.Col).Text)) SkipCellChange = False End Sub ''' ''' 表格鼠标移动事件 ''' ''' ''' Private Sub Grid_MouseMove(Sender As Object, e As MouseEventArgs) Static lastRow As Integer = 0 Return If _skipMouseMoveChange Then Return If _grd.EditorVisible Then Return '编辑状态 Dim row As Integer = _grd.MouseRow Dim node As RowNode = FindRowNode(row) If lastRow = row Then Return '过滤相同行 If node Is Nothing Then Return If row < _drawRow OrElse row >= _grd.Rows Then Return '过滤无效行 If node.RowType = RowNode.RowTypeEnum.DeviceGroup Then Return '取消移动事件 LockGridAutoRedraw() '取消上一次显示背景色 If lastRow > _drawRow Then node = FindRowNode(lastRow) If node Is Nothing Then UnLockGridAutoRedraw() Return End If If node.RowType > RowNode.RowTypeEnum.HotelRoomType Then Dim endRow As Integer = IIf(lastRow + node.AllChildCount >= _grd.Rows, _grd.Rows - 1, lastRow + node.AllChildCount) Try _grd.Range(lastRow, ColNames.Action, endRow, ColNames.Max - 1).BackColor = Color.White Catch ex As Exception _grd.Range(lastRow, ColNames.Action, _grd.Rows - 1, ColNames.Max - 1).BackColor = Color.White End Try End If End If '添加当前节点的背景色 node = FindRowNode(row) If node Is Nothing Then UnLockGridAutoRedraw() Return End If If node.RowType > RowNode.RowTypeEnum.HotelRoomType Then Dim endRow As Integer = IIf(row + node.AllChildCount >= _grd.Rows, _grd.Rows - 1, row + node.AllChildCount) _grd.Range(row, ColNames.Action, endRow, ColNames.Max - 1).BackColor = Color.LemonChiffon End If lastRow = row UnLockGridAutoRedraw() End Sub ''' ''' 表格鼠标轴滚动事件 ''' ''' ''' Private Sub Grid_MouseWheel(Sender As Object, e As MouseEventArgs) Static isWheel As Boolean = False If _flgControl = False Then Return If isWheel Then Return isWheel = True If e.Delta > 0 Then If _zoomNum < 4 Then _zoomNum += 0.05 If _zoomNum > 4 Then _zoomNum = 4 Zoom(_zoomNum) End If Else If _zoomNum > 0.6 Then _zoomNum += -0.05 If _zoomNum < 0.6 Then _zoomNum = 0.6 Zoom(_zoomNum) End If End If isWheel = False End Sub ''' ''' 表格放大至指定倍数 ''' ''' 放大倍数 Private Sub Zoom(num As Single) LockGridAutoRedraw() _grd.DefaultFont = New Font("宋体", _defaultFontSize * num) _grd.DefaultRowHeight = _defaultRowHeight * num For row As Integer = 0 To _grd.Rows - 1 _grd.Row(row).Height = _defaultRowHeight * num Next For col As Integer = 0 To _grd.Cols - 1 _grd.Column(col).Width = _defaultColumnWidths(col) * num Next For row As Integer = 0 To _grd.Rows - 1 For col As Integer = 0 To _grd.Cols - 1 _grd.Cell(row, col).FontSize = _defaultFontSize * num Next Next UnLockGridAutoRedraw() End Sub #End Region #Region "表格存储与读取" Private _gIsLoading As Boolean = False '装载过程标记,在装载中简化格式显示以加快装载速度 Public Function Load(path As String) As Boolean Try _gIsLoading = True InitGrid() InitGridErrList() InitTreeView() Dim xd As New XmlDocument() xd.Load(path) Dim xe As XmlElement Dim nodeList As XmlNodeList = xd.SelectSingleNode($"RcuConfig").ChildNodes For Each node As XmlNode In nodeList xe = CType(node, XmlElement) Select Case xe.LocalName Case "RowNodes" _rootNode.Clear() Dim tmpModelName As String = "" Dim tmpIsModelName As Boolean = False LoadRowNodes(xe.ChildNodes, _rootNode.Nodes) Case "BasicClassFilename" BasicClassFilename = xe.InnerText Case "ConctionFilename" ConditionFileName = xe.InnerText Case Else Throw New Exception($"LoadXml untreated localName:{xe.LocalName}") End Select Next ' DebugPrintTimeSpent("4 Start Refresh Grid") '刷新表格 LockGridAutoRedraw() SkipCellChange = True FillGridByRootNode(_rootNode.Nodes(0)) SkipCellChange = False UnLockGridAutoRedraw() ' DebugPrintTimeSpent("5 Complete Refresh Grid") _isCellChanged = False '复位文件修改标记’ CellNav_Clear() _gIsLoading = False _gIsFristMergeCell = True Return True Catch ex As Exception CellNav_Clear() _gIsLoading = False Return False End Try End Function ''' ''' 加载行节点 ''' ''' ''' Public Sub LoadRowNodes(xmlNodes As XmlNodeList, nodes As RowNodes, Optional ByRef ModelName As String = "", Optional ByRef IsModelName As Boolean = False) Dim xe As XmlElement For Each xmlNode As XmlNode In xmlNodes Console.WriteLine($"{xmlNode.GetType.Name }--{xmlNode.GetType.Name }") xe = CType(xmlNode, XmlElement) Select Case xe.LocalName Case "RowNode" Dim node As New RowNode node.Name = xe.GetAttribute("Name") Dim type As String = xe.GetAttribute("RowType") 'Momo 2022-09-06 装载XML时提取出机型名称 If type = "Model" Then _RcuModelName = node.Name End If Dim rowType As RowNode.RowTypeEnum = [Enum].Parse(GetType(RowNode.RowTypeEnum), type) node.RowType = rowType Dim tag As Object = StringToTag(rowType, xe.GetAttribute("Tag")) node.Tag = tag LoadRowNode(xe, node) '获取子节点,填充内容 nodes.Add(node) Case Else Throw New Exception($"LoadRowNodes Unknown LocalName:{xe.LocalName}") End Select Next End Sub ''' ''' 读取表格xml时,根据不同行节点类型,还原Tag属性 ''' ''' ''' ''' Private Function StringToTag(type As RowNode.RowTypeEnum, tagString As String) As Object If String.IsNullOrEmpty(tagString) Then Return Nothing Dim result As Object Select Case type Case RowNode.RowTypeEnum.HotelRoomType result = JsonConvert.DeserializeObject(Of HotelRoomTypeRowNodeTag)(tagString) Case RowNode.RowTypeEnum.ExternalModel result = JsonConvert.DeserializeObject(Of ModelRowNodeTag)(tagString) Case RowNode.RowTypeEnum.Model result = JsonConvert.DeserializeObject(Of ModelRowNodeTag)(tagString) Case RowNode.RowTypeEnum.DeviceAttribute, RowNode.RowTypeEnum.ModelAttribute Dim tmp As AttributeRowNodeTag = JsonConvert.DeserializeObject(Of AttributeRowNodeTag)(tagString) tmp.DealRangeString() tmp.Value = tmp.Value result = tmp Case RowNode.RowTypeEnum.ModelAttribute_DeviceExists Dim tmp As AttributeRowNodeTag = JsonConvert.DeserializeObject(Of AttributeRowNodeTag)(tagString) tmp.DealRangeString() tmp.Value = tmp.Value result = tmp Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD result = JsonConvert.DeserializeObject(Of XiaoBaoRowNodeTag)(tagString) Case RowNode.RowTypeEnum.DeviceObject result = JsonConvert.DeserializeObject(Of DeviceObjectRowNodeTag)(tagString) Case RowNode.RowTypeEnum.DeviceEvent result = JsonConvert.DeserializeObject(Of DeviceEventRowNodeTag)(tagString) Case RowNode.RowTypeEnum.DeviceEventActionMode Dim tmp As AttributeRowNodeTag = JsonConvert.DeserializeObject(Of AttributeRowNodeTag)(tagString) tmp.DealRangeString() tmp.Value = tmp.Value result = tmp Case RowNode.RowTypeEnum.DeviceEventConditions Dim tmp As AttributeRowNodeTag = JsonConvert.DeserializeObject(Of AttributeRowNodeTag)(tagString) tmp.DealRangeString() tmp.Value = tmp.Value result = tmp Case RowNode.RowTypeEnum.DeviceEventAction result = JsonConvert.DeserializeObject(Of DeviceEventActionRowNodeTag)(tagString) Case Else result = Nothing End Select Return result End Function Public Sub LoadRowNode(xmlElement As XmlElement, node As RowNode) Dim xe As XmlElement For Each xmlNode As XmlNode In xmlElement.ChildNodes xe = CType(xmlNode, XmlElement) Select Case xe.LocalName Case "Action" node.Action = Boolean.Parse(xe.InnerText) Case "Expanded" node.Expanded = Boolean.Parse(xe.InnerText) Case "Visible" node.Visible = Boolean.Parse(xe.InnerText) Case "Text" node.Text = xe.InnerText Case "Attribute" node.DeviceType = xe.InnerText Case "DeviceAlias" node.DeviceAlias = xe.InnerText Case "DeviceType" node.DeviceType = xe.InnerText Case "Interface" node.Interface = xe.InnerText Case "DEV_TYPE_DATA" node.DEV_TYPE_DATA = xe.InnerText Case "PROTOCOL_VER" node.PROTOCOL_VER = xe.InnerText Case "DeviceName" node.DeviceName = xe.InnerText Case "DeviceMothed" node.DeviceMothed = xe.InnerText Case "DelayTime" node.DelayTime = xe.InnerText Case "DelayUnit" node.DelayUnit = xe.InnerText Case "Param" Dim name As String = xe.GetAttribute("Name") Dim type As String = xe.GetAttribute("DataType") Dim range As String = xe.GetAttribute("DataRange") Dim rangeValue As String = xe.GetAttribute("DataRangeValue") Dim defaultVal As String = xe.GetAttribute("DataDefault") Dim desc As String = xe.GetAttribute("Desc") Dim param As New AttributeRowNodeTag(name, type, range, rangeValue, desc, defaultVal) With {.Value = xe.InnerText} node.Params.Add(param) Case "RowNodes" LoadRowNodes(xe.ChildNodes, node.Nodes) End Select ' Console.WriteLine(node.Text & ":" & node.DeviceType & "," & node.DeviceName & vbCrLf) Next End Sub ''' ''' 保存模型信息至Xml文件 ''' ''' xml完整路径 ''' Public Function Save(OuputFullName As String) As Boolean Dim xws As New XmlWriterSettings Try With xws .Indent = True .NewLineOnAttributes = False .Encoding = New UTF8Encoding(False) End With IO.Directory.CreateDirectory(OuputFullName.Substring(0, OuputFullName.LastIndexOf("\"))) Using xw As XmlWriter = XmlWriter.Create(OuputFullName, xws) xw.WriteStartDocument() xw.WriteStartElement($"RcuConfig") '创建跟节点 '新建基类文件名节点 xw.WriteStartElement($"BasicClassFilename") '创建表属性节点 xw.WriteString(BasicClassFilename) xw.WriteEndElement() '新建条件文件名节点 xw.WriteStartElement($"ConctionFilename") '创建表属性节点 xw.WriteString(ConditionFileName) xw.WriteEndElement() xw.WriteStartElement($"RowNodes") '创建表属性节点 For Each node As RowNode In _rootNode.Nodes WriteRowNodeToXml(xw, node) Next xw.WriteEndElement() xw.WriteEndElement() xw.WriteEndDocument() End Using _isCellChanged = False '复位文件修改标记 Return True Catch ex As Exception MsgBox($"保存文件失败,{ex.Message}") Return False End Try End Function Public Sub SetLockingState(Islockstate As String) Dim nodelist As New List(Of RowNode) Dim tag As AttributeRowNodeTag For Each node As RowNode In _rootNode.RowList If String.IsNullOrEmpty(node.Text) Then Continue For If node.Text.Contains("判断锁定状态") Then 'Console.WriteLine(node.ParentNode.ParentNode.ParentNode.ParentNode.ParentNode.Text) ''Console .WriteLine (node .ParentNode .ParentNode .ParentNode.ParentNode .Text ) 'Console.WriteLine(node.ParentNode.ParentNode.ParentNode.Text) 'Console.WriteLine(node.Text) 'Console.WriteLine(node.DeviceType) node.DeviceType = Islockstate nodelist.Add(node) End If Next LockGridAutoRedraw() SkipCellChange = True For Each node As RowNode In nodelist FillRowText(node) tag= node.Tag tag.Value = node.DeviceType Next SkipCellChange = False UnLockGridAutoRedraw() ''刷新表格 'Try ' LockGridAutoRedraw() ' SkipCellChange = True ' FillGridByRootNode(_rootNode.Nodes(0),False ) ' SkipCellChange = False ' UnLockGridAutoRedraw() ' ' DebugPrintTimeSpent("5 Complete Refresh Grid") ' _isCellChanged = False '复位文件修改标记’ ' CellNav_Clear() ' _gIsLoading = False ' _gIsFristMergeCell = True 'Catch ex As Exception ' CellNav_Clear() ' _gIsLoading = False 'End Try End Sub ''' ''' 写入行节点内容至Xml字段 ''' ''' xml写入流 ''' 行节点 Private Sub WriteRowNodeToXml(xw As XmlWriter, node As RowNode) xw.WriteStartElement($"RowNode") '创建表属性节点 xw.WriteAttributeString("RowType", $"{node.RowType}") xw.WriteAttributeString("Name", $"{node.Name}") xw.WriteAttributeString("Tag", $"{JsonConvert.SerializeObject(node.Tag)}") xw.WriteElementString("Action", $"{node.Action}") xw.WriteElementString("Expanded", $"{node.Expanded}") xw.WriteElementString("Visible", $"{node.Visible}") xw.WriteElementString("DeviceAlias", $"{node.DeviceAlias}") xw.WriteElementString("Text", $"{node.Text}") Select Case node.RowType Case RowNode.RowTypeEnum.HotelRoomType'酒店房型 Case RowNode.RowTypeEnum.Model'模型 Case RowNode.RowTypeEnum.ModelAttributes'模型属性组 Case RowNode.RowTypeEnum.ModelAttribute '模型属性 xw.WriteElementString("Attribute", $"{node.DeviceType}") Case RowNode.RowTypeEnum.DeviceGroup '设备组 xw.WriteElementString("Interface", $"{node.Interface }") xw.WriteElementString("DEV_TYPE_DATA", $"{node.DEV_TYPE_DATA }") xw.WriteElementString("PROTOCOL_VER", $"{node.PROTOCOL_VER }") Case RowNode.RowTypeEnum.DeviceObject '设备对象 xw.WriteElementString("DeviceType", $"{node.DeviceType}") xw.WriteElementString("Interface", $"{node.Interface }") Case RowNode.RowTypeEnum.DeviceAttributes'设备属性组 Case RowNode.RowTypeEnum.DeviceAttribute '设备属性 xw.WriteElementString("Attribute", $"{node.DeviceType}") Case RowNode.RowTypeEnum.DeviceEvents'事件组 Case RowNode.RowTypeEnum.DeviceEvent '事件 xw.WriteElementString("DeviceType", $"{node.DeviceType}") Case RowNode.RowTypeEnum.DeviceEventActionMode '执行方式 xw.WriteElementString("DeviceType", $"{node.DeviceType}") Case RowNode.RowTypeEnum.DeviceEventConditions xw.WriteElementString("DeviceType", $"{node.DeviceType}") Case RowNode.RowTypeEnum.ModelAttribute_DeviceExists '设备存在 xw.WriteElementString("DeviceType", $"{node.DeviceType}") Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD '小宝命令集 xw.WriteElementString("DeviceType", $"{node.DeviceType}") xw.WriteElementString("DeviceName", $"{node.DeviceName}") Case RowNode.RowTypeEnum.DeviceEventAction xw.WriteElementString("DeviceType", $"{node.DeviceType}") xw.WriteElementString("DeviceName", $"{node.DeviceName}") xw.WriteElementString("DeviceMothed", $"{node.DeviceMothed}") xw.WriteElementString("DelayTime", $"{node.DelayTime}") xw.WriteElementString("DelayUnit", $"{node.DelayUnit}") For Each param As AttributeRowNodeTag In node.Params xw.WriteStartElement($"Param") '创建表属性节点 xw.WriteAttributeString("Name", param.Name) xw.WriteAttributeString("DataType", $"{param.Type}") xw.WriteAttributeString("DataRange", param.RangeString) xw.WriteAttributeString("DataRangeValue", param.DataRangeValue) xw.WriteAttributeString("DataDefault", param.DefalutValue) xw.WriteAttributeString("Desc", param.Description) xw.WriteString($"{param.Value}") xw.WriteEndElement() Next Case RowNode.RowTypeEnum.ContextualModel xw.WriteElementString("DeviceType", $"{node.DeviceType}") Case RowNode.RowTypeEnum.DeviceEventActions xw.WriteElementString("DeviceType", $"{node.DeviceType}") End Select xw.WriteStartElement($"RowNodes") '创建表属性节点 For Each cNode As RowNode In node.Nodes WriteRowNodeToXml(xw, cNode) Next xw.WriteEndElement() xw.WriteEndElement() End Sub ''' ''' 表格导出为Xls文件 ''' ''' Public Sub ExportToXls(strXlsFileName As String) _grd.ExportToExcel(strXlsFileName) End Sub ''' ''' 导出当前选择的行节点至外部模型文件 ''' ''' 导出文件的路径 Public Sub ExportRowNode(path As String) If _grd Is Nothing Then Throw New Exception("当前未绑定表格") If _grd.ActiveCell Is Nothing Then Throw New Exception("当前未选择表格单元") Dim row As Integer = _grd.ActiveCell.Row Dim node As RowNode = FindRowNode(row) Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventActions,'动作组 RowNode.RowTypeEnum.DeviceEventAllActions,'动作集 RowNode.RowTypeEnum.ContextualModel,'场景 RowNode.RowTypeEnum.ContextualModels '场景集 Dim xws As New XmlWriterSettings With xws .Indent = True .NewLineOnAttributes = False .Encoding = New UTF8Encoding(False) End With Using xw As XmlWriter = XmlWriter.Create(path, xws) xw.WriteStartDocument() xw.WriteStartElement($"ExportNode") '创建跟节点 xw.WriteStartElement($"RowNodes") '创建表属性节点 WriteRowNodeToXml(xw, node) xw.WriteEndElement() xw.WriteEndElement() xw.WriteEndDocument() End Using Case Else Throw New Exception("当前行节点不支持导出") End Select End Sub ''' ''' 导入外部模型至指定节点下 ''' ''' 导入文件的路径 Public Sub ImportRowNode(path As String) If _grd Is Nothing Then Throw New Exception("当前未绑定表格") If _grd.ActiveCell Is Nothing Then Throw New Exception("当前未选择表格单元") Dim row As Integer = _grd.ActiveCell.Row Dim node As RowNode = FindRowNode(row) Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventActions,'动作组 RowNode.RowTypeEnum.DeviceEventAllActions,'动作集 RowNode.RowTypeEnum.ContextualModel,'场景 RowNode.RowTypeEnum.ContextualModels '场景集 Dim tmpNode As New RowNode Dim xd As New XmlDocument() xd.Load(path) Dim xe As XmlElement Dim nodeList As XmlNodeList = xd.SelectSingleNode($"ExportNode").ChildNodes For Each n As XmlNode In nodeList xe = CType(n, XmlElement) Select Case xe.LocalName Case "RowNodes" LoadRowNodes(xe.ChildNodes, tmpNode.Nodes) Case Else Throw New Exception($"未知的XML节点元素名:{xe.LocalName}") End Select Next If tmpNode.Count = 0 Then Throw New Exception("当前XML无有效节点") tmpNode = tmpNode.Nodes(0) If node.RowType <> tmpNode.RowType Then Throw New Exception($"当前选择节点类型与模型文件节点类型不匹配") LockGridAutoRedraw() SkipCellChange = True For Each n As RowNode In tmpNode.Nodes node.AddNode(n) AddNodeRow(n, True) '填充已使用设备类型 _usedDevTypes.AddNode(n) Next SkipCellChange = False UnLockGridAutoRedraw() Case Else Throw New Exception("当前行节点不支持导出") End Select End Sub #End Region #Region "表格方法" Public Sub New(ByRef tsp As ToolStripProgressBar) _tsp = tsp _rootNode = New RowNode _drawRow = 1 _drawCol = ColNames.Node ShowNodeIcon = False _autoRedraw = False _defaultRowHeight = 19 _defaultFontSize = 9 _zoomNum = 1 _usedDevTypes = UsedDeviceTypes.CreateSingleton _defaultColumnWidths = New List(Of Short) _defaultColumnWidths.Add(32) _defaultColumnWidths.Add(20) _defaultColumnWidths.Add(150) _defaultColumnWidths.Add(230) For col As Integer = ColNames.DeviceType To ColNames.DeviceName _defaultColumnWidths.Add(100) Next For col As Integer = ColNames.DeviceMothed To ColNames.Max - 1 _defaultColumnWidths.Add(100) Next _undoManager = New CommandManager _compiler = New RowNodeCompile(_rootNode) AddHandler _compiler.OutputPrint, AddressOf CompilePrint _rsmObject = New RowNodeCompile(_rootNode) '资源管理器对象 _rsm_KeyPair_objectGroups = New Dictionary(Of Integer, RowNode) '资源管理-》对象列表’ _rsm_KeyPair_actionGroups = New Dictionary(Of Integer, RowNode) '资源管理器-》动作列表’ _rsm_KeyPair_contextualGroups = New Dictionary(Of Integer, RowNode) '资源管理器-》场景列表’ _rsm_KeyPair_xiaobao = New Dictionary(Of Integer, RowNode) '资源管理器-》小宝列表’ _errCellList = New Dictionary(Of Integer, ErrCellSturc) '标记错误单元格,以便在fillStyle中对错误个以颜色高亮标注 InitTreeView() _ruleCheckGobleErrList = New Dictionary(Of Integer, RuleCheckErrList) '规则检查错误列表’ CellNav_Clear() CreateErrHightTimer() '启动定时任务,定时闪烁错误单元格的背景色 compilerupdanodetext() End Sub Protected Friend Sub LockGridAutoRedraw() If _grd Is Nothing Then Return If _tv Is Nothing Then Return If _autoRedraw = 0 Then _grd.AutoRedraw = False _tv.BeginUpdate() End If _autoRedraw += 1 End Sub Protected Friend Sub UnLockGridAutoRedraw() If _grd Is Nothing Then Return If _tv Is Nothing Then Return _autoRedraw -= 1 If _autoRedraw = 0 Then _grd.AutoRedraw = True _grd.Refresh() _tv.EndUpdate() ' _tv.Refresh() End If End Sub Private Sub InitTreeView() _rsm_rootNode.Text = "资源管理器" _rsm_rootNode.NodeFont = New Font("宋体", 9, FontStyle.Bold) _rsm_rootNode.ForeColor = Color.MediumVioletRed _rsm_rootNode.ImageKey = "04167.ico" _rsm_node_objectGroups.Nodes.Clear() _rsm_node_actionGroups.Nodes.Clear() _rsm_node_contextualGroups.Nodes.Clear() _rsm_node_xiaobao.Nodes.Clear() _rsm_node_objectGroups.Text = "设备" _rsm_node_objectGroups.NodeFont = New Font("宋体", 9, FontStyle.Bold) _rsm_node_objectGroups.ForeColor = Color.DeepSkyBlue _rsm_node_objectGroups.ImageKey = "设备组.ico" _rsm_node_actionGroups.Text = "动作组" _rsm_node_actionGroups.NodeFont = New Font("宋体", 9, FontStyle.Bold) _rsm_node_actionGroups.ForeColor = Color.DeepSkyBlue _rsm_node_actionGroups.ImageKey = "动作组.ico" _rsm_node_contextualGroups.Text = "场景" _rsm_node_contextualGroups.NodeFont = New Font("宋体", 9, FontStyle.Bold) _rsm_node_contextualGroups.ForeColor = Color.DeepSkyBlue _rsm_node_contextualGroups.ImageKey = "场景.ico" _rsm_node_xiaobao.Text = "小宝词条" _rsm_node_xiaobao.NodeFont = New Font("宋体", 9, FontStyle.Bold) _rsm_node_xiaobao.ForeColor = Color.DeepSkyBlue _rsm_node_xiaobao.ImageKey = "05434.ico" _rsm_rootNode.Nodes.Clear() _rsm_rootNode.Nodes.Add(_rsm_node_objectGroups) '"设备" _rsm_rootNode.Nodes.Add(_rsm_node_actionGroups) '"动作组" _rsm_rootNode.Nodes.Add(_rsm_node_contextualGroups) '"场景" _rsm_rootNode.Nodes.Add(_rsm_node_xiaobao) '"小宝词条" End Sub Public Sub InitGridErrList() With _grdErrLst .NewFile() .DefaultRowHeight = 20 .Cols = GridErrLstColNames.MAX .Rows = 1 .DisplayRowNumber = True '首列显示数字 .ExtendLastCol = True '最后一列自动扩充 .GridColor = Color.White '.BorderStyle = BorderStyleEnum.None .DefaultFont = New Font("宋体", 9) .DefaultRowHeight = _defaultRowHeight .ForeColorComment = Color.Black .AllowUserResizing = False '不允许用户调节单元格大小 .HideGridLines = True .BackColorFixed = Color.White .Locked = True .Column(GridErrLstColNames.fixedColume).Visible = False .Range(0, 0, 0, .Cols - 1).BackColor = Color.LightGray .Range(0, 0, 0, .Cols - 1).Borders(FlexCell.EdgeEnum.Outside) = LineStyleEnum.None .Column(GridErrLstColNames.ID).Alignment = AlignmentEnum.CenterCenter .Column(GridErrLstColNames.ErrType).Alignment = AlignmentEnum.CenterCenter .Column(GridErrLstColNames.RowNodeIdx).Alignment = AlignmentEnum.CenterCenter .Column(GridErrLstColNames.ErrMsg).Alignment = AlignmentEnum.LeftCenter .Column(GridErrLstColNames.ID).Width = 30 .Column(GridErrLstColNames.ErrType).Width = 20 .Column(GridErrLstColNames.RowNodeIdx).Width = 35 '.Column(GridErrLstColNames.ErrMsg).Width = 10 '最后一行自适应 .Column(GridErrLstColNames.ErrType).CellType = CellTypeEnum.DefaultType .Column(GridErrLstColNames.ID).CellType = CellTypeEnum.TextBox .Cell(0, GridErrLstColNames.ID).Text = "序号" .Cell(0, GridErrLstColNames.ErrType).Text = "" .Cell(0, GridErrLstColNames.RowNodeIdx).Text = "行号" .Cell(0, GridErrLstColNames.ErrMsg).Text = "说明" .Cell(0, GridErrLstColNames.ErrMsg).Alignment = AlignmentEnum.CenterCenter End With AddImageToGrid() End Sub Public Sub InitGrid(Optional model As DeviceModel = Nothing) LockGridAutoRedraw() SkipCellChange = True With _grd .Rows = 1 .Cols = ColNames.Max .DrawMode = DrawModeEnum.OwnerDraw '绘制方式为自绘 .DisplayRowNumber = True '首列显示数字 .ExtendLastCol = True '最后一列自动扩充 .EnterKeyMoveTo = MoveToEnum.NextRow '.HideGridLines = True '影藏表格线 .GridColor = Color.FromArgb(240, 240, 240) .BorderStyle = BorderStyleEnum.None .DefaultFont = New Font("宋体", 9) .DefaultRowHeight = _defaultRowHeight .ForeColorComment = Color.Black .Range(0, 0, 0, .Cols - 1).Font = New Font($"宋体", 9) '首行样式 '设置列宽 .Column(ColNames.ID).Width = _defaultColumnWidths(ColNames.ID) .Column(ColNames.Action).Width = _defaultColumnWidths(ColNames.Action) .Column(ColNames.DeviceAlias).Width = _defaultColumnWidths(ColNames.DeviceAlias) .Column(ColNames.Node).Width = _defaultColumnWidths(ColNames.Node) For col As Integer = ColNames.DeviceType To ColNames.Max - 1 .Column(col).Width = _defaultColumnWidths(col) Next '设置列类型 .Column(ColNames.DeviceAlias).Alignment = AlignmentEnum.RightCenter .Column(ColNames.Action).CellType = CellTypeEnum.CheckBox .Column(ColNames.Node).Locked = True .Column(ColNames.DeviceName).CellType = CellTypeEnum.ComboBox .Column(ColNames.DeviceMothed).CellType = CellTypeEnum.ComboBox .Column(ColNames.DelayTime).CellType = CellTypeEnum.ComboBox .Column(ColNames.DelayTime).Mask = MaskEnum.Digital .Column(ColNames.DelayUnit).CellType = CellTypeEnum.ComboBox .ComboBox(0).Locked = True .ComboBox(0).DropDownWidth = 140 .ComboBox(ColNames.DeviceName).Locked = False .ComboBox(ColNames.DeviceName).Sorted = True .ComboBox(ColNames.DeviceName).DropDownWidth = 160 .ComboBox(ColNames.DeviceMothed).Locked = False .ComboBox(ColNames.DeviceMothed).Sorted = True .ComboBox(ColNames.DeviceMothed).DropDownWidth = 160 .ComboBox(ColNames.DelayTime).DisplayMember = "请选择时间" .ComboBox(ColNames.DelayTime).Items.Add("0") .ComboBox(ColNames.DelayTime).Items.Add("1") .ComboBox(ColNames.DelayTime).Items.Add("10") .ComboBox(ColNames.DelayTime).Items.Add("20") .ComboBox(ColNames.DelayTime).Items.Add("50") .ComboBox(ColNames.DelayTime).Items.Add("100") .ComboBox(ColNames.DelayTime).Items.Add("200") .ComboBox(ColNames.DelayTime).Items.Add("255") .ComboBox(ColNames.DelayTime).AutoComplete = True .ComboBox(ColNames.DelayTime).SelectedIndex = 0 .ComboBox(ColNames.DelayUnit).Items.Add("ms") .ComboBox(ColNames.DelayUnit).Items.Add("s") .ComboBox(ColNames.DelayUnit).Items.Add("m") .ComboBox(ColNames.DelayUnit).Items.Add("h") .ComboBox(ColNames.DelayUnit).Items.Add("d") .ComboBox(ColNames.DelayUnit).AutoComplete = True .ComboBox(ColNames.DelayUnit).Locked = True .ComboBox(ColNames.DelayUnit).SelectedIndex = 0 '设置列名 Dim names() As String = EnumExtender.GetEnumAllDesc(GetType(ColNames)) For col As Integer = ColNames.ID To ColNames.Max - 1 .Cell(0, col).Text = names(col) '设置列名 Next '合并参数单元格 For i = 0 To MaxParamCount - 1 .Range(0, ColNames.ParamDesc1 + i * 2, 0, ColNames.ParamValue1 + i * 2).Merge() Next End With '清空上一表格缓存 _rootNode.Nodes.Clear() _usedDevTypes.Clear() _undoManager.ClearCommands() '清空错误列表缓存 _ruleCheckGobleErrList.Clear() '填充缓存 If model IsNot Nothing Then _rootNode.AddNode(AppendHotelRoomTypeNode(model)) '填充表格 FillGridByRootNode(_rootNode.Nodes(0)) End If _gIsFristMergeCell = True SkipCellChange = False UnLockGridAutoRedraw() CellNav_Clear() _isCellChanged = False '复位文件修改标记’ End Sub Private Sub tvNodeClear() _rsm_node_objectGroups.Nodes.Clear() _rsm_node_actionGroups.Nodes.Clear() _rsm_node_contextualGroups.Nodes.Clear() _rsm_node_xiaobao.Nodes.Clear() End Sub ''' ''' 在别名更改后,同步更改动作调用的名称,并返回修改的个数 ''' ''' ''' ''' ''' Public Function UpdateDeviceAliceName(argNode As RowNode, argBeforeAliceName As String, argAfterAliceName As String) As Integer LockGridAutoRedraw() SkipCellChange = True Dim tmpModifiedCount As Integer = 0 Select Case argNode.RowType '对象的别名调用,要同时修改动作和对象路径 Case RowNode.RowTypeEnum.DeviceObject ' 9.模型外设对象 For Each node As RowNode In _rootNode.RowList If node.RowType = RowNode.RowTypeEnum.DeviceEventAction Then '23 动作 If node.DeviceName Is Nothing Then Continue For If node.DeviceName.Length > 0 AndAlso '修改前的设备名不为空 node.DeviceName = argBeforeAliceName Then '名称必须匹配 If argNode.DeviceType IsNot Nothing Then '如果传入节点有DevType则必须匹配DevType选项 If node.DeviceType = argNode.DeviceType Then node.DeviceName = argAfterAliceName tmpModifiedCount += 1 End If Else node.DeviceName = argAfterAliceName tmpModifiedCount += 1 End If End If '更新显示’ FillRowText(node) FillRowStyle(node) End If 'S1:首先找到对象节点 If node.RowType = RowNode.RowTypeEnum.DeviceObject Then '9.模型外设对象 'S2:为该对象节点重新更新对象路径 Dim tmpPath As String = "" If GetObjectPath(node, tmpPath) = True Then 'S3:将对象路径写入到对象的DeviceName中 node.DeviceMothed = tmpPath 'tmpModifiedCount += 1 End If '更新显示’ FillRowText(node) FillRowStyle(node) End If Next '动作组会被动作调用,因此则两者的别名该表,会触发修改动作的调用名称 Case RowNode.RowTypeEnum.DeviceEventActions ' 22.模型外设事件执行动作组 For Each node As RowNode In _rootNode.RowList If node.RowType = RowNode.RowTypeEnum.DeviceEventAction Then '23 动作 If node.DeviceName Is Nothing Then Continue For If node.DeviceName.Length > 0 AndAlso '修改前的设备名不为空 node.DeviceName = argBeforeAliceName Then '名称必须匹配 If argNode.DeviceType IsNot Nothing Then '如果传入节点有DevType则必须匹配DevType选项 If node.DeviceType = argNode.DeviceType Then node.DeviceName = argAfterAliceName tmpModifiedCount += 1 End If Else node.DeviceName = argAfterAliceName tmpModifiedCount += 1 End If End If '更新显示’ FillRowText(node) FillRowStyle(node) End If Next '如下项目的修改,主要会影响对象路径,因此需要更新修改节点所属的子节点对象的属性 Case RowNode.RowTypeEnum.ModelAttributeGroup, ' 6.主机模型属性分组 RowNode.RowTypeEnum.DeviceGroup, ' 8.模型外设组 RowNode.RowTypeEnum.ModelAttributes, ' 5.主机模型属性集 RowNode.RowTypeEnum.Model, ' 4.主机模型 RowNode.RowTypeEnum.ExternalModel ' 26.外设模型 For Each node As RowNode In _rootNode.RowList 'S1:首先找到对象节点 If node.RowType = RowNode.RowTypeEnum.DeviceObject Then '9.模型外设对象 'S2:为该对象节点重新更新对象路径 Dim tmpPath As String = "" If GetObjectPath(node, tmpPath) Then 'S3:将对象路径写入到对象的DeviceName中 node.DeviceMothed = tmpPath tmpModifiedCount += 1 End If 'S4:调用fillRowtext方法更新显示 '更新显示’ FillRowText(node) FillRowStyle(node) End If Next tmpModifiedCount = 0 '避免触发修改后弹信息框 End Select SkipCellChange = False UnLockGridAutoRedraw() Return tmpModifiedCount End Function ''' ''' 填充表格选择单元格提示信息 ''' ''' 表格选择列 ''' 表格对应行节点信息 ''' Private Function FillTipString(col As Integer, node As RowNode) As TipChangedEventArgs Dim colName As String = _grd.Cell(0, col).Text Dim title As String = $"{node.Text} - {_grd.Cell(0, col).Text}" Dim tipString As New StringBuilder Dim tmpStrRowLevelFamily As String = "" 'Dim tmpNode As RowNode = node 'While tmpNode.Lever > 1 ' tmpNode = tmpNode.ParentNode ' tmpStrRowLevelFamily = tmpNode.Text & "(-)" & tmpStrRowLevelFamily 'End While tmpStrRowLevelFamily = node.Lever & ":" & node.Text title = title & vbCrLf & "RowIdx:" & node.RowListIndex & " RowType:" & node.RowType & " RowLevel:" & tmpStrRowLevelFamily title = title & vbCrLf & "DevAlias:" & node.DeviceAlias & " DevName:" & node.DeviceName & " DevType:" & node.DeviceType title = title & vbCrLf & "DevInterface:" & node.Interface & " DEV_TYPE_DATA:" & node.DEV_TYPE_DATA & " PROTOCOL_VER:" & node.PROTOCOL_VER tipString.Append($"当前位置:[{node.RowListIndex},{col}]{vbCrLf}") ' tipString.Append($"{colName}:{_grd.Cell(node.RowListIndex, col).Text}{vbCrLf}") Select Case col Case ColNames.Action tipString.Append($"说明:勾选时则当前行内容参与编译,反之不参与编译{vbCrLf}") Case ColNames.DeviceAlias tipString.Append($"说明:设备别名,可根据需要命令,参与填充动作行内容{vbCrLf}") Case ColNames.Node tipString.Append($"说明:当前行的功能说明{vbCrLf}") Case ColNames.DeviceType Select Case node.RowType Case RowNode.RowTypeEnum.ModelAttribute Dim tag As AttributeRowNodeTag = node.Tag tipString.Append($"说明:模型属性[{tag.Name}]的属性值{vbCrLf}") tipString.Append($"参数名称:{tag.Name} tag.ValueData:{tag.ValueData}{vbCrLf}") If String.IsNullOrEmpty(tag.Description) = False Then tipString.Append($"参数说明:{tag.Description}{vbCrLf}") tipString.Append($"参数类型:{tag.Type}{vbCrLf}") tipString.Append($"参数范围:{tag.RangeString}{vbCrLf}") Case RowNode.RowTypeEnum.DeviceObject Dim tag As DeviceObjectRowNodeTag = node.Tag tipString.Append($"说明:设备[{tag.Device.Name}]的设备类型{vbCrLf}") tipString.Append($"参数名称:设备类型 DeviceType:{node.DeviceType}{vbCrLf}") tipString.Append($"参数说明:不同的设备类型,包含不同的属性,方法,事件{vbCrLf}") tipString.Append($"参数类型:{AttributeRowNodeTag.DataTypes.List}{vbCrLf}") tipString.Append($"参数范围:{String.Join(",", tag.Device.BaseClasses.GetAllClassName)}{vbCrLf}") Case RowNode.RowTypeEnum.DeviceAttribute Dim tag As AttributeRowNodeTag = node.Tag tipString.Append($"说明:设备属性[{tag.Name}]的属性值{vbCrLf}") tipString.Append($"参数名称:{tag.Name} tag.ValueData:{tag.ValueData}{vbCrLf}") If String.IsNullOrEmpty(tag.Description) = False Then tipString.Append($"参数说明:{tag.Description}{vbCrLf}") tipString.Append($"参数类型:{tag.Type}{vbCrLf}") tipString.Append($"参数范围:{tag.RangeString}{vbCrLf}") Case RowNode.RowTypeEnum.DeviceEventActionMode Dim tag As AttributeRowNodeTag = node.Tag tipString.Append($"说明:事件执行参数[{tag.Name}]的属性值{vbCrLf}") tipString.Append($"参数名称:{tag.Name} tag.ValueData:{tag.ValueData}{vbCrLf}") If String.IsNullOrEmpty(tag.Description) = False Then tipString.Append($"参数说明:{tag.Description}{vbCrLf}") tipString.Append($"参数类型:{tag.Type}{vbCrLf}") tipString.Append($"参数范围:{tag.RangeString}{vbCrLf}") Case RowNode.RowTypeEnum.DeviceEventConditions Dim tag As AttributeRowNodeTag = node.Tag tipString.Append($"说明:事件执行条件[{tag.Name}]的属性值{vbCrLf}") tipString.Append($"参数名称:{tag.Name} tag.ValueData:{tag.ValueData}{vbCrLf}") If String.IsNullOrEmpty(tag.Description) = False Then tipString.Append($"参数说明:{tag.Description}{vbCrLf}") tipString.Append($"参数类型:{tag.Type}{vbCrLf}") tipString.Append($"参数范围:{tag.RangeString}{vbCrLf}") Case RowNode.RowTypeEnum.DeviceEventAction tipString.Append($"说明:动作关联的设备类型{vbCrLf}") tipString.Append($"参数名称:设备类型{vbCrLf}") tipString.Append($"参数类型:{AttributeRowNodeTag.DataTypes.List}{vbCrLf}") tipString.Append($"参数范围:所有参与使用的设备类型{vbCrLf}") End Select Case ColNames.DeviceName Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction tipString.Append($"说明:动作关联的{colName}{vbCrLf}") tipString.Append($"参数名称:{colName}{vbCrLf}") tipString.Append($"参数类型:{AttributeRowNodeTag.DataTypes.List}{vbCrLf}") tipString.Append($"参数范围:对应设备类型下的所有设备别名{vbCrLf}") End Select Case ColNames.DeviceMothed Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction tipString.Append($"说明:动作关联的{colName}{vbCrLf}") tipString.Append($"参数名称:{colName}{vbCrLf}") tipString.Append($"参数说明:{vbCrLf}") tipString.Append($"参数类型:{AttributeRowNodeTag.DataTypes.List}{vbCrLf}") tipString.Append($"参数范围:对应设备类型下的所有设备方法{vbCrLf}") End Select Case ColNames.DelayTime Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction tipString.Append($"说明:动作关联的{colName}{vbCrLf}") End Select Case ColNames.DelayUnit Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction tipString.Append($"说明:动作关联的{colName}{vbCrLf}") End Select Case ColNames.ParamDesc1, ColNames.ParamDesc2, ColNames.ParamDesc3, ColNames.ParamDesc4, ColNames.ParamDesc5, ColNames.ParamDesc6 Dim index As Integer = (col - ColNames.ParamDesc1) \ 2 tipString.Append($"说明:动作关联方法的第{index + 1}个参数名称{vbCrLf}") Case ColNames.ParamValue1, ColNames.ParamValue2, ColNames.ParamValue3, ColNames.ParamValue4, ColNames.ParamValue5, ColNames.ParamValue6 Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventAction Dim index As Integer = (col - ColNames.ParamValue1) \ 2 If index < node.Params.Count Then Dim tag As AttributeRowNodeTag = node.Params(index) tipString.Append($"说明:动作关联方法的第{index + 1}个参数值{vbCrLf}") tipString.Append($"参数名称:{tag.Name}{vbCrLf}") If String.IsNullOrEmpty(tag.Description) = False Then tipString.Append($"参数说明:{tag.Description}{vbCrLf}") tipString.Append($"参数类型:{tag.Type}{vbCrLf}") tipString.Append($"参数范围:{tag.RangeString}{vbCrLf}") End If End Select Case Else End Select Return New TipChangedEventArgs(title, tipString.ToString) End Function ''' ''' 强制刷新同级的行数并显示出来,应对某些情况表格变更后没有及时刷新 ''' Public Sub ForceRefreshGridRows(argNode As RowNode) If argNode.Lever <= 2 Then Return Dim tmpNode As RowNode = argNode.ParentNode '获取父级 Dim tmpChildCnt As Integer = tmpNode.Count If tmpChildCnt >= 1 Then For i = 0 To tmpChildCnt - 1 _grd.Row(tmpNode.RowListIndex + 1 + i).Visible = True Next End If End Sub ''' ''' 循环嵌套调用,直到节点类型为对象组或级数小于=3 ''' ''' Public Sub UpdateActionCnt(argNode As RowNode) Dim tmpFatherNode As RowNode = argNode If tmpFatherNode.RowType = RowNode.RowTypeEnum.DeviceGroup OrElse ' 8.模型外设组 tmpFatherNode.Lever <= 2 Then '停止嵌套调用 Return Else '嵌套调用 tmpFatherNode = tmpFatherNode.ParentNode If UpdateChildActionCount(tmpFatherNode) = True Then UpdateActionCnt(tmpFatherNode) Else Return End If End If End Sub ''' ''' 获取节点下的动作数量,注意是节点下所有动作,如果有多级子节点,会全部统计到一起 ''' ''' 输入节点,只对部分节点有效 Public Function UpdateChildActionCount(argNode As RowNode) As Boolean Dim argAvailabCnt As Integer = 0 Dim argTotalCnt As Integer = 0 Select Case argNode.RowType Case RowNode.RowTypeEnum.DeviceEventActions, ' 22.模型外设事件执行动作组 RowNode.RowTypeEnum.DeviceEvent, ' 15.模型外设事件 RowNode.RowTypeEnum.ContextualModel, ' 25.情景模式 RowNode.RowTypeEnum.DeviceObject ' 9.对象 Dim tmpNodeLst As New List(Of RowNode) If argNode.GetAllChildsNodeList(argNode, tmpNodeLst) = True Then For Each tmpNode As RowNode In tmpNodeLst If tmpNode.RowType = RowNode.RowTypeEnum.DeviceEventAction Then ' 23.模型外设事件执行动作 argTotalCnt += 1 If tmpNode.DeviceName <> "" Then argAvailabCnt += 1 End If Next argNode.DeviceName = argAvailabCnt & "/" & argTotalCnt FillRowText(argNode) Else Return False End If Case Else 'Return False End Select Return True End Function ''' ''' 获取对象的路径,一直溯源到第2级(RCU型号级),并将路径保存在 argStrPath 中供显示 ''' Public Function GetObjectPath(argNode As RowNode, ByRef argStrPath As String) As Boolean Try Dim tmpNode As RowNode = argNode 'If argNode.RowType <> RowNode.RowTypeEnum.DeviceObject Then Return False '9 模型外设对象 If tmpNode.Lever <= 2 Then Return False argStrPath = " > " & tmpNode.Text While tmpNode.Lever > 2 tmpNode = tmpNode.ParentNode If String.IsNullOrEmpty(tmpNode.DeviceAlias) Then argStrPath = " > " & tmpNode.DeviceAlias & argStrPath Else argStrPath = " > " & tmpNode.Text & argStrPath End If End While Catch ex As Exception Return False End Try Return True End Function ''' ''' 禁用项视图 ''' Public Sub SetDisableItemView(isDisableItemView As Boolean) LockGridAutoRedraw() SkipCellChange = True '先全部展开 'ExpandRows(_rootNode) '_rootNode.ExpandAll() For Each node As RowNode In _rootNode.RowList 'If isDisableItemView = True Then ' _grd.Row(node.RowListIndex).Visible = node.Visible 'Else ' _grd.Row(node.RowListIndex).Visible = node.Action 'End If If node.Visible Then 'If = False Then _grd.Row(node.RowListIndex).Visible = isDisableItemView AndAlso node.Compile End If Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 默认视图 ''' Public Sub SetDefaultView() LockGridAutoRedraw() SkipCellChange = True '先全部展开 'ExpandRows(_rootNode) _rootNode.ExpandAll() For Each node As RowNode In _rootNode.RowList Select Case node.RowType Case RowNode.RowTypeEnum.ModelAttributes, ' 5.主机模型属性集 RowNode.RowTypeEnum.ModelAttributeGroup, ' 6.主机模型属性分组 RowNode.RowTypeEnum.DeviceAttributes, ' 10.模型外设属性组 RowNode.RowTypeEnum.DeviceEventActionModeGroup, ' 16.模型外设事件动作执行方式组 RowNode.RowTypeEnum.DeviceEventAllConditions ' 19.模型外设事件条件 CollapseRows(node) Case RowNode.RowTypeEnum.DeviceObject ' 9.模型外设对象 '如果模型对象下面没有动作组就收缩起来 Dim tmpObjectPath As String = "" If GetObjectPath(node, tmpObjectPath) = True Then node.DeviceMothed = tmpObjectPath FillRowText(node) End If UpdateChildActionCount(node) Dim tmpChildRowNodeList As New List(Of RowNode) If node.GetAllChildsNodeList(node, tmpChildRowNodeList) Then For Each tmpChildNode As RowNode In tmpChildRowNodeList If tmpChildNode.RowType = RowNode.RowTypeEnum.DeviceEventActions Then Exit Select ' 22.模型外设事件执行动作组 Next End If CollapseRows(node) Case RowNode.RowTypeEnum.DeviceEvent, ' 15.模型外设事件 RowNode.RowTypeEnum.ContextualModel ' 25.情景模式 UpdateChildActionCount(node) CollapseRows(node) Case RowNode.RowTypeEnum.DeviceEventActions ' 22.模型外设事件执行动作组 Dim tmpObjectPath As String = "" If GetObjectPath(node, tmpObjectPath) = True Then node.DeviceMothed = tmpObjectPath FillRowText(node) End If UpdateChildActionCount(node) End Select '更新格式’ FillRowStyle(node) Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 指定节点向上溯源,所有的父节点都显示出来 ''' ''' 开始溯源的起点 ''' 溯源结束的目标级数 Public Sub SetParentNodesVisible(argStartNode As RowNode, argEndNodeLevel As Integer) Dim tmpNode As RowNode = argStartNode If argStartNode.Lever > argEndNodeLevel Then '向上:一直向上溯源到目标级别,所有父级节点都显示出来 While tmpNode.Lever > argEndNodeLevel tmpNode = tmpNode.ParentNode tmpNode.Visible = True _grd.Row(tmpNode.RowListIndex).Visible = True End While End If End Sub ''' ''' 指定节点,将其父系节点逐级展开 ''' ''' Private Sub SetRowFamilyExpand(argRow As RowNode) LockGridAutoRedraw() SkipCellChange = True Dim tmpNodeFamilyList As List(Of RowNode) = New List(Of RowNode) Dim tmpFatherNode As RowNode = argRow '直系上级节点加入列表 While tmpFatherNode.Lever > 1 tmpNodeFamilyList.Add(tmpFatherNode) tmpFatherNode = tmpFatherNode.ParentNode End While '全表遍历,将直系节点逐级展开 For Each tmpNode As RowNode In _rootNode.RowList If tmpNode.Nodes.Count > 0 Then tmpNode.Expand() End If Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 指定节点和其同类节点显示或隐藏 ''' ''' 传入节点类型,函数会自动匹配同类节点并进行相应操作 ''' 显示状态 Public Sub SetRowsVisible(rowType As RowNode.RowTypeEnum, visible As Boolean) ' 属性:5,6,7,10,13, ' 端口:9, ' 动作:21,22,23 ' 场景:25 ' 条件:16,17,19,20 LockGridAutoRedraw() SkipCellChange = True For Each node As RowNode In _rootNode.RowList Select Case rowType '属性、属性组 Case RowNode.RowTypeEnum.DeviceAttribute If node.RowType = RowNode.RowTypeEnum.ModelAttribute OrElse node.RowType = RowNode.RowTypeEnum.ModelAttributeGroup OrElse node.RowType = RowNode.RowTypeEnum.ModelAttributes OrElse node.RowType = RowNode.RowTypeEnum.DeviceAttribute OrElse node.RowType = RowNode.RowTypeEnum.DeviceAttributes Then _grd.Row(node.RowListIndex).Visible = visible End If '条件组 Case RowNode.RowTypeEnum.DeviceEventAllConditions If node.RowType = RowNode.RowTypeEnum.DeviceEventAllConditions OrElse node.RowType = RowNode.RowTypeEnum.DeviceEventConditions OrElse node.RowType = RowNode.RowTypeEnum.DeviceEventActionMode OrElse node.RowType = RowNode.RowTypeEnum.DeviceEventActionModeGroup Then _grd.Row(node.RowListIndex).Visible = visible End If Case Else End Select Next SkipCellChange = False UnLockGridAutoRedraw() End Sub Public Sub SetRowsShowActionGroup(argShowMode As Integer) LockGridAutoRedraw() SkipCellChange = True Dim tmpNode As New RowNode _rootNode.ExpandAll() For Each node As RowNode In _rootNode.RowList Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventActions If argShowMode = 1 Then '显示全部动作组 CollapseRows(node) node.Visible = True _grd.Row(node.RowListIndex).Visible = True ElseIf argShowMode = 2 Then '仅显示有别名的动作组 If String.IsNullOrEmpty(node.DeviceAlias) Then CollapseRows(node) node.Visible = False _grd.Row(node.RowListIndex).Visible = False Else CollapseRows(node) node.Visible = True _grd.Row(node.RowListIndex).Visible = True End If End If Case RowNode.RowTypeEnum.DeviceEventAction Case Else node.Visible = False _grd.Row(node.RowListIndex).Visible = False ''向上:一直向上溯源到第3级,所有父级节点都显示出来 'SetParentNodesVisible(node, 3) End Select ' Case RowNode.RowTypeEnum.ModelAttributes, ' RowNode.RowTypeEnum.DeviceObject, ' RowNode.RowTypeEnum.DeviceEventAllActions, ' RowNode.RowTypeEnum.ContextualModels ' CollapseRows(node) ' Case RowNode.RowTypeEnum.ExternalModel ' node.Visible = True ' _grd.Row(node.RowListIndex).Visible = True ' CollapseRows(node) ' '向上:一直向上溯源到第3级,所有父级节点都显示出来 ' SetParentNodesVisible(node, 3) ' '向下:遍历所有子节点,仅显示对象 ' Dim tmpAllChildCnt As Integer = node.AllChildCount ' For i = node.RowListIndex To node.RowListIndex + tmpAllChildCnt ' tmpNode = FindRowNode(i) ' '仅显示对象节点’ ' If tmpNode.RowType = RowNode.RowTypeEnum.DeviceObject Then ' SetParentNodesVisible(tmpNode, 3) ' tmpNode.Visible = True ' _grd.Row(tmpNode.RowListIndex).Visible = True ' CollapseRows(tmpNode) ' End If ' Next 'End Select Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 仅显示对象节点,其余节点收缩起来 ''' Public Sub SetRowsShowObject() LockGridAutoRedraw() SkipCellChange = True Dim tmpNode As New RowNode For Each node As RowNode In _rootNode.RowList Select Case node.RowType Case RowNode.RowTypeEnum.ModelAttributes, RowNode.RowTypeEnum.DeviceObject, RowNode.RowTypeEnum.DeviceEventAllActions, RowNode.RowTypeEnum.ContextualModels CollapseRows(node) Case RowNode.RowTypeEnum.ExternalModel node.Visible = True _grd.Row(node.RowListIndex).Visible = True CollapseRows(node) '向上:一直向上溯源到第3级,所有父级节点都显示出来 SetParentNodesVisible(node, 3) '向下:遍历所有子节点,仅显示对象 Dim tmpAllChildCnt As Integer = node.AllChildCount For i = node.RowListIndex To node.RowListIndex + tmpAllChildCnt tmpNode = FindRowNode(i) '仅显示对象节点’ If tmpNode.RowType = RowNode.RowTypeEnum.DeviceObject Then SetParentNodesVisible(tmpNode, 3) tmpNode.Visible = True _grd.Row(tmpNode.RowListIndex).Visible = True CollapseRows(tmpNode) End If Next End Select Next MergeCell() '合并单元格 SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 收缩行节点 ''' ''' Public Sub CollapseRows(node As RowNode) node.Collapse() For i As Integer = 1 To node.AllChildCount _grd.Row(node.RowListIndex + i).Visible = False Next End Sub ''' ''' 默认视图 ''' Public Sub ExpandAllNodes() LockGridAutoRedraw() SkipCellChange = True _rootNode.ExpandAll() For Each node As RowNode In _rootNode.RowList FillRowStyle(node) Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 展开行节点 ''' ''' Public Sub ExpandRows(node As RowNode) node.Expand() For Each child As RowNode In node.Nodes _grd.Row(child.RowListIndex).Visible = True '如果子节点上一次为收缩的,则展开依旧为收缩的 If child.Count <= 0 Then Continue For If child.Expanded Then ExpandRows(child) Next End Sub ''' ''' 通过行号查找对应的行节点信息 ''' ''' ''' Protected Friend Function FindRowNode(row As Integer) As RowNode If row >= _rootNode.RowList.Count Or row < 1 Then Return Nothing Return _rootNode.RowList.Item(row) End Function ''' ''' 添加行 ''' ''' 添加行的类型 ''' 添加行数 Public Sub AddRow(type As RowNode.RowTypeEnum, count As Integer) If _grd Is Nothing Then Throw New Exception($"表格未关联") If _grd.ActiveCell Is Nothing Then Throw New Exception($"未选择有效的设备位置") If _rootNode.Count = 0 Then Throw New Exception($"模型未初始化") Dim node As RowNode = FindRowNode(_grd.ActiveCell.Row) If node Is Nothing Then Throw New Exception($"未获取到节点信息") If CheckNodeParent(node.RowType, type) = False Then Return LockGridAutoRedraw() Dim nodes As New List(Of RowNode) Dim cNode As RowNode For i = 0 To count - 1 '添加内存行 cNode = CreateRowNode(type) nodes.Add(cNode) Next UnLockGridAutoRedraw() _undoManager.RunCommand(New AddNodeRowsCommand(Me, nodes)) End Sub ''' ''' 添加设备行 ''' ''' 设备模型 ''' 添加行数 Public Sub AddRow(model As DeviceModel, count As Integer, Optional IsInterval As Boolean = False) If _grd Is Nothing Then Throw New Exception($"表格未关联") If _grd.ActiveCell Is Nothing Then Throw New Exception($"未选择有效的设备位置") If _rootNode.Count = 0 Then Throw New Exception($"模型未初始化") Dim node As RowNode = FindRowNode(_grd.ActiveCell.Row) If node Is Nothing Then Throw New Exception($"未获取到节点信息") If CheckNodeParent(node.RowType, RowNode.RowTypeEnum.Model) = False Then Return Dim tag As DeviceObjectRowNodeTag = node.Tag If String.Compare(tag.Device.Interface, model.Desc.DevInterface, True) = 0 Then LockGridAutoRedraw() Dim nodes As New List(Of RowNode) Dim cNode As RowNode For i = 0 To count - 1 '添加内存行 cNode = AppendDeviceModelNode(model, IsInterval) nodes.Add(cNode) Next UnLockGridAutoRedraw() _undoManager.RunCommand(New AddNodeRowsCommand(Me, nodes)) Else Throw New Exception($"父节点接口类型[{tag.Device.Interface}]与新增节点接口类型[{model.Desc.DevInterface}]不匹配") End If End Sub ''' ''' 校验当前行类型是否允许添加的指定父行类型下 ''' ''' ''' ''' Protected Friend Function CheckNodeParent(pType As RowNode.RowTypeEnum, type As RowNode.RowTypeEnum) As Boolean Dim result As Boolean Select Case type Case RowNode.RowTypeEnum.ContextualModel If pType = RowNode.RowTypeEnum.ContextualModels Then result = True Case RowNode.RowTypeEnum.DeviceEventActions If pType = RowNode.RowTypeEnum.DeviceEventAllActions Then result = True Case RowNode.RowTypeEnum.DeviceEventConditionItem If pType = RowNode.RowTypeEnum.DeviceEvent OrElse pType = RowNode.RowTypeEnum.ContextualModel Then result = True Case RowNode.RowTypeEnum.DeviceEventAction If pType = RowNode.RowTypeEnum.DeviceEventActions Then result = True Case RowNode.RowTypeEnum.Model If pType = RowNode.RowTypeEnum.DeviceObject OrElse pType = RowNode.RowTypeEnum.HotelRoomType Then result = True Case Else Throw New Exception($"非法的行节点类型:{type}") End Select Return result End Function ''' ''' 新增行时,创建对应类型行节点(可以考虑将所有节点的生成都集成在这个函数里) ''' ''' ''' Protected Friend Function CreateRowNode(type As RowNode.RowTypeEnum) As RowNode Dim node As New RowNode Select Case type Case RowNode.RowTypeEnum.ContextualModel node.RowType = RowNode.RowTypeEnum.ContextualModel node.Name = $"场景{Now:yyMMdd_HHmmssfff}" node.Text = $"场景:{Now:yyMMdd_HHmmssfff}" node.DeviceType = "场景" _usedDevTypes.AddNode(node) node.AddNode(CreateRowNode(RowNode.RowTypeEnum.DeviceEventConditionItem)) Case RowNode.RowTypeEnum.DeviceEventActions node.RowType = RowNode.RowTypeEnum.DeviceEventActions node.Name = $"动作组{Now:yyMMdd_HHmmssfff}" node.Text = $"动作组:{Now:yyMMdd_HHmmssfff}" node.DeviceType = "动作组" _usedDevTypes.AddNode(node) node.AddNode(CreateRowNode(RowNode.RowTypeEnum.DeviceEventAction)) Case RowNode.RowTypeEnum.DeviceEventConditionItem '2022-04-12 按XML文件加载条件,条件放在 Condictions 变量中 'Step 1:添加条件节点 node.RowType = RowNode.RowTypeEnum.DeviceEventConditionItem node.Name = $"事件条件" node.Text = $"事件条件" 'Step 2.1: 添加执行方式组 Dim rnExeModes As New RowNode rnExeModes.RowType = RowNode.RowTypeEnum.DeviceEventActionModeGroup rnExeModes.Name = "执行方式" rnExeModes.Text = "执行方式" node.AddNode(rnExeModes) '添加参数项 For Each exeMode As Conction In Condictions.ExeMode rnExeModes.AddNode(AppendActionMode(exeMode)) Next 'Step 2.2: 添加参数组 Dim rnCondictions As New RowNode rnCondictions.RowType = RowNode.RowTypeEnum.DeviceEventAllConditions rnCondictions.Name = "条件参数" rnCondictions.Text = "条件参数" node.AddNode(rnCondictions) '添加参数项 For Each condiction As Conction In Condictions.Conction rnCondictions.AddNode(AppendActionCondition(condiction)) Next 'Step 3:添加一个动作组 node.AddNode(CreateRowNode(RowNode.RowTypeEnum.DeviceEventActions)) Case RowNode.RowTypeEnum.DeviceEventAction node.RowType = RowNode.RowTypeEnum.DeviceEventAction node.Name = $"动作" node.Text = $"动作:" node.Tag = New DeviceEventActionRowNodeTag Case Else node.RowType = type Throw New Exception("当前节点类型不支持创建") End Select Return node End Function ''' ''' 添加场景模式行 ''' ''' 添加数量 Public Sub AddModel(Optional count As Integer = 1) AddRow(RowNode.RowTypeEnum.ContextualModel, count) End Sub ''' ''' 添加动作组行 ''' ''' 添加数量 Public Sub AddActions(Optional count As Integer = 1) AddRow(RowNode.RowTypeEnum.DeviceEventActions, count) End Sub ''' ''' 添加设备对象 ''' Public Sub AddDeviceObject(model As DeviceModel, Optional count As Integer = 1, Optional IsInterval As Boolean = False) AddRow(model, count, IsInterval) End Sub ''' ''' 添加事件条件 ''' Public Sub AddEventCondition(Optional count As Integer = 1) AddRow(RowNode.RowTypeEnum.DeviceEventConditionItem, count) End Sub ''' ''' 添加动作行 ''' ''' Public Sub AddEventAction(Optional count As Integer = 1) AddRow(RowNode.RowTypeEnum.DeviceEventAction, count) End Sub ''' ''' 移除当前选中行 ''' Public Sub RemoveActiveNode() If _grd Is Nothing Then Throw New Exception($"表格未关联") If _grd.ActiveCell Is Nothing Then Throw New Exception($"未选择有效的设备位置") If _rootNode.Count = 0 Then Throw New Exception($"模型未初始化") Dim node As RowNode = FindRowNode(_grd.ActiveCell.Row) If node Is Nothing Then Throw New Exception($"未获取到节点信息") Select Case node.RowType Case RowNode.RowTypeEnum.ContextualModel Case RowNode.RowTypeEnum.DeviceEventActions Case RowNode.RowTypeEnum.DeviceEventConditionItem Case RowNode.RowTypeEnum.DeviceEventAction Case Else Throw New Exception($"当前选中节点[{node.Text}]不允许删除") End Select '移除数据行 LockGridAutoRedraw() _grd.Range(node.RowListIndex, 1, node.RowListIndex + node.AllChildCount, 1).DeleteByRow() UnLockGridAutoRedraw() '移除节点 node.Remove() End Sub ''' ''' 移除当前选中节点 ''' Public Sub RemoveSelectNode() If _grd Is Nothing Then Throw New Exception($"表格未关联") If _grd.ActiveCell Is Nothing Then Throw New Exception($"未选择有效的设备位置") If _rootNode.Count = 0 Then Throw New Exception($"模型未初始化") Dim node As RowNode = FindRowNode(_grd.ActiveCell.Row) If node Is Nothing Then Throw New Exception($"未获取到节点信息") Select Case node.RowType Case RowNode.RowTypeEnum.DeviceEventActions Case RowNode.RowTypeEnum.DeviceEventConditionItem Case RowNode.RowTypeEnum.DeviceEventAction Case Else Throw New Exception($"当前选中节点[{node.Text}]不允许删除") End Select '移除数据行 LockGridAutoRedraw() _grd.Range(node.RowListIndex, 1, node.RowListIndex + node.AllChildCount, 1).DeleteByRow() UnLockGridAutoRedraw() '移除节点 node.Remove() End Sub ''' ''' 插入行 ''' Public Sub InsertRows() _undoManager.RunCommand(New InsertRowsCommand(Me)) End Sub ''' ''' 删除行 ''' Public Sub DeleteRows() _undoManager.RunCommand(New DeleteRowsCommand(Me)) End Sub Protected Friend Sub UpdateGrid(moveDownRow As Integer, moveDownCount As Integer, moveUpRow As Integer, moveUpCount As Integer) LockGridAutoRedraw() '更新控件 If moveUpCount < moveDownCount Then '表格行上移 For i As Integer = 0 To moveUpCount - 1 _grd.Row(moveUpRow + i).Position = moveDownRow + i Next Else '表格行下移 While moveDownCount > 0 _grd.Row(moveDownRow).Position = moveUpRow + moveUpCount - 1 moveDownCount -= 1 End While End If UnLockGridAutoRedraw() End Sub ''' ''' 上移行 ''' Public Sub MoveUpRows() _undoManager.RunCommand(New MoveUpCommand(Me)) End Sub ''' ''' 下移行 ''' Public Sub MoveDownRows() _undoManager.RunCommand(New MoveDownCommand(Me)) End Sub ''' ''' 复制行 ''' Public Sub CopyRows() Dim grd As FlexCell.Grid = _grd Dim sb As New StringBuilder For i = grd.Selection.FirstRow To grd.Selection.LastRow sb.Append(grd.Cell(i, grd.Selection.FirstCol).Text) For j = grd.Selection.FirstCol + 1 To grd.Selection.LastCol sb.Append(vbTab & grd.Cell(i, j).Text) Next sb.Append(vbCrLf) Next Clipboard.SetText(sb.ToString) Return Clipboard.SetData("DeviceModel", New DemoClass) End Sub ''' ''' 剪切行 ''' Public Sub CutRows() _undoManager.RunCommand(New CutRowsCommand(Me)) Return Clipboard.SetData("DeviceModel", New DemoClass) Dim grd As FlexCell.Grid = _grd End Sub ''' ''' 粘贴行 ''' Public Sub PasteRows() If Clipboard.ContainsText Then _undoManager.RunCommand(New PasteRowsCommand(Me)) End If Return Console.WriteLine($"Formats:{String.Join(",", Clipboard.GetDataObject.GetFormats())}") If Clipboard.GetDataObject.GetDataPresent("DeviceModel") Then Dim b As DemoClass = CType(Clipboard.GetDataObject.GetData("DeviceModel"), DemoClass) Console.WriteLine($"S:{b}") Else Console.WriteLine($"Fail!") End If Dim idate As Object = Clipboard.GetData("DeviceModel") If idate Is Nothing Then Return Dim demo As DemoClass = CType(idate, DemoClass) If demo Is Nothing Then MsgBox("解析失败") ': Return Console.WriteLine($"Demo:{demo}") End Sub ''' ''' 撤销 ''' Public Sub Undo() _undoManager.Undo() End Sub ''' ''' 重做 ''' Public Sub Redo() _undoManager.Redo() End Sub ''' ''' 启用行 ''' Public Sub EnableRows() If _grd Is Nothing Then Throw New Exception($"表格未关联") If _grd.Selection Is Nothing Then Throw New Exception($"未选择有效的设备位置") If _rootNode.Count = 0 Then Throw New Exception($"模型未初始化") _grd.Cell(_grd.ActiveCell.Row, ColNames.Action).Text = "1" End Sub ''' ''' 禁用行 ''' Public Sub DisableRows() If _grd Is Nothing Then Throw New Exception($"表格未关联") If _grd.Selection Is Nothing Then Throw New Exception($"未选择有效的设备位置") If _rootNode.Count = 0 Then Throw New Exception($"模型未初始化") Dim node As RowNode = FindRowNode(_grd.ActiveCell.Row) Select Case node.RowType Case RowNode.RowTypeEnum.ContextualModel, RowNode.RowTypeEnum.DeviceEventConditionItem, RowNode.RowTypeEnum.DeviceEventAction, RowNode.RowTypeEnum.DeviceEventActions _grd.Cell(_grd.ActiveCell.Row, ColNames.Action).Text = "0" Case Else Throw New Exception($"当前节点不支持禁用") End Select End Sub #End Region #Region "编译" ''' ''' 配置信息数据结构 ''' Public Structure ConfigInfoStuct Dim Author As String Dim ConfigToolVersion As String Dim ReleaseDate As Date Dim HotelName As String Dim HotelCode As Integer Dim HotelGroupName As String Dim RoomTypeName As String Dim CfgFileVersion As Integer Dim ConfigModelName As string End Structure ''' ''' 配置信息,有些信息需要从App传过来 ''' Public _ConfigInfo As ConfigInfoStuct '''' '''' 传递项目信息,这些信息将会被编译在0x01数据块 '''' '''' 'Public Function SetConfigInfo(configInfo As ConfigInfoStuct) As Boolean ' _ConfigInfo = configInfo ' Return True 'End Function ''' ''' 编译生成编译文件 ''' Public Function Compile(argErrMsg As String, datPath As String, Optional ByVal dic As List(Of Dictionary(Of String, String)) = Nothing) As Boolean _tsp.Maximum = _grd.Rows _tsp.Value = 0 Dim onoff As Boolean = _compiler.Complie(argErrMsg, _ConfigInfo, _tsp, datPath, dic) _tsp.Value = _grd.Rows Return onoff End Function Public Sub compilerupdanodetext() AddHandler _compiler.updanodetext, Sub(node As RowNode) FillRowText(node) End Sub End Sub Public Function FindRcuName() As String For Each node As RowNode In _rootNode.RowList If node.RowType = RowNode.RowTypeEnum.Model Then _RcuModelName = node.Name Exit For End If Next Return _RcuModelName End Function #End Region #Region "向前,向后导航" Dim _isCellLeave_push As Boolean = True '是否记录cell leave事件 Structure GridCellLocation Dim row As Integer Dim col As Integer End Structure Public stCellNav_Prev As Stack = New Stack Public stCellNav_Next As Stack = New Stack ''' ''' 向前导航 ''' Public Sub CellNav_Prev() If stCellNav_Next.Count < 1 Then Return Dim cellLocation As GridCellLocation = stCellNav_Next.Pop stCellNav_Prev.Push(cellLocation) _grd.Cell(cellLocation.row, cellLocation.col).SetFocus() End Sub ''' ''' 向后导航 ''' Public Sub CellNav_Next() If stCellNav_Prev.Count < 1 Then Return Dim cellLocation As GridCellLocation = stCellNav_Prev.Pop stCellNav_Next.Push(cellLocation) _grd.Cell(cellLocation.row, cellLocation.col).SetFocus() End Sub ''' ''' 清除栈数据 ''' Public Sub CellNav_Clear() stCellNav_Prev.Clear() stCellNav_Prev.Clear() End Sub ''' ''' 向后导航步骤数 ''' ''' Public Function GetCellNav_NextCnt() As Integer Return stCellNav_Next.Count End Function ''' ''' 向前导航步骤数 ''' ''' Public Function GetCellNav_PrevCnt() As Integer Return stCellNav_Prev.Count End Function #End Region #Region "规则检查" Public Structure RuleCheckErrList ''' ''' 错误项的 node index ''' Dim err_rowRowIdx As Integer ''' ''' 错误项的列,与node index一起定位到具体的单元格 ''' Dim err_col As Integer ''' ''' 错误类型 ''' Dim err_errType As RuleCheckErrTypeEnum ''' ''' 错误信息 ''' Dim err_errMsg As String ''' ''' 错误项的node信息 ''' Dim err_node As RowNode End Structure Public Structure ErrCellSturc Dim cell_Row As Integer Dim cell_Col As Integer Dim err_Type As RuleCheckErrTypeEnum End Structure ''' ''' 用于保存全局规则检测的错误项 ''' Dim _ruleCheckGobleErrList As Dictionary(Of Integer, RuleCheckErrList) Dim _errIconKey() As String = {"OK", "Warning", "Error"} Dim tmpErrorCellBackColor As Boolean Public Enum RuleCheckErrTypeEnum ''' ''' 规则检查结果 - 没问题 ''' RuleCheck_OK ''' ''' 规则检查结果 - 警告:某些规则不太符合,可以编译但是可能会产生不确定的后果 ''' RuleCheck_Warning ''' ''' 规则检查结果 - 错误:严重错误,不可编译或确定会导致不正确的后果 ''' RuleCheck_Error End Enum Public Sub CreateErrHightTimer(Optional ByRef IsEnable As Boolean = True) 'Dim atimer As Timer = New Timer() 'AddHandler atimer.Elapsed, New ElapsedEventHandler(AddressOf Timer_ErrorCellHightLight) '到达时间的时候执行事件; 'atimer.Interval = 1000 '设置引发时间的时间间隔 此处设置为1秒(1000毫秒) 'atimer.AutoReset = True '设置是执行一次(false)还是一直执行(true); 'atimer.Enabled = True '是否执行System.Timers.Timer.Elapsed事件; 'If IsEnable = True Then ' atimer.Start() 'Else ' atimer.Stop() 'End If End Sub Private Sub Timer_ErrorCellHightLight() If _ruleCheckGobleErrList Is Nothing OrElse _ruleCheckGobleErrList.Count = 0 Then Return Dim tmpColor As Color tmpErrorCellBackColor = Not tmpErrorCellBackColor If tmpErrorCellBackColor Then tmpColor = Color.Salmon Else tmpColor = Color.White End If Try '_grd.AutoRedraw = False For Each node As RowNode In _rootNode.RowList If _ruleCheckGobleErrList.ContainsKey(node.RowListIndex) Then Dim errInfo As RuleCheckErrList = _ruleCheckGobleErrList(node.RowListIndex) If _ruleCheckGobleErrList.ContainsKey(node.RowListIndex) AndAlso errInfo.err_errType = RuleCheckErrTypeEnum.RuleCheck_Error Then _grd.Cell(node.RowListIndex, errInfo.err_col).BackColor = tmpColor End If End If Next '_grd.Refresh() '_grd.AutoRedraw = True Catch ex As Exception End Try End Sub Private _grdErrlst_mouseMove_event_lastRow As Integer = 0 Private _errCellList As New Dictionary(Of Integer, ErrCellSturc) ''' ''' 错误列表的mouse move事件 ''' ''' ''' Private Sub GridErrLst_MouseMove(Sender As Object, e As MouseEventArgs) If _grdErrLst.EditorVisible Then Return '编辑状态 Dim row As Integer = _grdErrLst.MouseRow If _grdErrlst_mouseMove_event_lastRow = row Then Return '过滤相同行 If row <= 0 OrElse row >= _grdErrLst.Rows Then Return '过滤无效行 _grdErrLst.AutoRedraw = False '取消上一次显示背景色 _grdErrLst.Range(1, GridErrLstColNames.RowNodeIdx, _grdErrLst.Rows - 1, _grdErrLst.Cols - 1).BackColor = Color.White '添加当前节点的背景色 _grdErrLst.Range(row, GridErrLstColNames.RowNodeIdx, row, _grdErrLst.Cols - 1).BackColor = Color.Yellow _grdErrlst_mouseMove_event_lastRow = row _grdErrLst.Refresh() _grdErrLst.AutoRedraw = True End Sub Private Sub GridErrLst_DoubleClick(Sender As Object, e As EventArgs) If _grdErrLst.EditorVisible Then Return '处于编辑状态 Dim tmpRowIdx As Integer = _grdErrLst.Cell(_grdErrLst.MouseRow, GridErrLstColNames.RowNodeIdx).Text Dim tmpRowNode As RowNode = FindRowNode(tmpRowIdx) If tmpRowNode Is Nothing Then Return LockGridAutoRedraw() SkipCellChange = True '展开节点的所有直系父节点,一直追溯到0级 SetRowFamilyExpand(tmpRowNode) '指定节点的单元格获取焦点 _grd.Cell(tmpRowIdx, 2).SetFocus() _grd.Range(tmpRowIdx, ColNames.DeviceAlias, tmpRowIdx, ColNames.DelayUnit).SelectCells() '重新整表刷新格式 For Each node As RowNode In _rootNode.RowList FillRowStyle(node) Next SkipCellChange = False UnLockGridAutoRedraw() End Sub ''' ''' 将错误图标加入到ImageList中,程序启动时添加一次即可 ''' Private Sub AddImageToGrid() Try 'Dim OK_ImagePath As String = Application.StartupPath & "\Images\OK.ico" 'Dim Warning_ImagePath As String = Application.StartupPath & "\Images\Warning.ico" 'Dim Error_ImagePath As String = Application.StartupPath & "\Images\Error.ico" '_grdErrLst.Images.Add(OK_ImagePath, "OK") '_grdErrLst.Images.Add(Warning_ImagePath, "Warning") '_grdErrLst.Images.Add(Error_ImagePath, "Error") 'E:\BLV_Sync\RD_PC\Project\BLV_Studio\SourceCode\BLV_Studio 'Images Dim Img As Bitmap Img = New Bitmap(MyBase.GetType().Assembly.GetManifestResourceStream("BLV_Studio.OK.bmp")) _grdErrLst.Images.Add(Img, "OK") Img = New Bitmap(MyBase.GetType().Assembly.GetManifestResourceStream("BLV_Studio.Warning.bmp")) _grdErrLst.Images.Add(Img, "Warning") Img = New Bitmap(MyBase.GetType().Assembly.GetManifestResourceStream("BLV_Studio.Error.bmp")) _grdErrLst.Images.Add(Img, "Error") Img.Dispose() Img = Nothing Catch ex As Exception 'MsgBox(ex.ToString) End Try End Sub Public _gIsEnableGobleRuleCheck As Boolean = True ''' ''' 启动一次全文规则检查,并返回错误数和告警数 ''' ''' 错误计数,错误计数为0则函数返回true ''' 告警计数,函数计数不影响函数返回 ''' Public Function StartGobleRuleCheck(ByRef ErrCount As Integer, ByRef WarningCount As Integer) As Boolean If _gIsEnableGobleRuleCheck = False Then Return True If _grd.Rows < 2 Then Return True Dim errType As RuleCheckErrTypeEnum Dim errMsg As String = "" Dim errCol As ColNames Dim errNodeStructure As RuleCheckErrList ErrCount = 0 WarningCount = 0 '错误列表先清空 _ruleCheckGobleErrList.Clear() _errCellList.Clear() '遍历所有node For Each node As RowNode In _rootNode.RowList '如果有错误则加入键值对’ If SignalRowNode_RuleCheck(node, errType, errMsg, errCol) <> True Then errNodeStructure.err_rowRowIdx = node.RowListIndex errNodeStructure.err_errType = errType errNodeStructure.err_errMsg = errMsg errNodeStructure.err_node = node errNodeStructure.err_col = errCol _ruleCheckGobleErrList.Add(errNodeStructure.err_rowRowIdx, errNodeStructure) '错误信息列表,将会显示到“错误列表”中 Else '’Console.WriteLine("RuleCheck RowIdx= " & node.RowListIndex & " :true") End If Next '将错误信息刷新到err Grid控件 _grdErrLst.AutoRedraw = False _grdErrLst.Rows = 1 Dim errGridRowIdx As Integer = 0 For Each errIdx As Integer In _ruleCheckGobleErrList.Keys errGridRowIdx += 1 _grdErrLst.Rows = _ruleCheckGobleErrList.Count + 1 Dim itemErrType = _ruleCheckGobleErrList(errIdx).err_errType _grdErrLst.Cell(errGridRowIdx, GridErrLstColNames.ErrType).SetImage(_errIconKey(itemErrType)) _grdErrLst.Cell(errGridRowIdx, GridErrLstColNames.ID).Text = errGridRowIdx _grdErrLst.Cell(errGridRowIdx, GridErrLstColNames.ErrMsg).Text = _ruleCheckGobleErrList(errIdx).err_errMsg _grdErrLst.Cell(errGridRowIdx, GridErrLstColNames.RowNodeIdx).Text = errIdx Select Case _ruleCheckGobleErrList(errIdx).err_errType Case RuleCheckErrTypeEnum.RuleCheck_OK Case RuleCheckErrTypeEnum.RuleCheck_Warning _grdErrLst.Range(errGridRowIdx, GridErrLstColNames.fixedColume, errGridRowIdx, GridErrLstColNames.MAX - 1).ForeColor = Color.Teal WarningCount += 1 Case RuleCheckErrTypeEnum.RuleCheck_Error _grdErrLst.Range(errGridRowIdx, GridErrLstColNames.fixedColume, errGridRowIdx, GridErrLstColNames.MAX - 1).ForeColor = Color.Brown ErrCount += 1 End Select Next _grdErrLst.Refresh() _grdErrLst.AutoRedraw = True _ruleChk_ErrCnt = ErrCount _ruleChk_WarningCnt = WarningCount If ErrCount > 0 Then Return False Else Return True End If End Function ''' ''' 单行规则确认,主要确认单行数据填写的完整性,以及数据类型是否合法 ''' ''' 被确认的节点 ''' 返回该节点的错误类型 ''' 返回该节点详细的错误信息 ''' Private Function SignalRowNode_RuleCheck(ByVal argRowNode As RowNode, ByRef ErrType As RuleCheckErrTypeEnum, ByRef ErrMsg As String, ByRef ErrCol As ColNames) As Boolean If argRowNode Is Nothing Then Return False If argRowNode.RowListIndex < 0 OrElse argRowNode.RowListIndex > _grd.Rows - 1 Then Return False ErrType = RuleCheckErrTypeEnum.RuleCheck_OK ErrMsg = "" ErrCol = ColNames.ID '根据不同的节点类型,执行不同的检测 Select Case argRowNode.RowType Case RowNode.RowTypeEnum.RootNode ' 0.根节点 Return True Case RowNode.RowTypeEnum.HotelGroup ' 1.酒店组 Return True Case RowNode.RowTypeEnum.Hotel ' 2.酒店项目 Return True Case RowNode.RowTypeEnum.HotelRoomType ' 3.酒店户型 Return True Case RowNode.RowTypeEnum.Model ' 4.主机模型 Return True Case RowNode.RowTypeEnum.ModelAttributes ' 5.主机模型属性集 Return True Case RowNode.RowTypeEnum.ModelAttributeGroup ' 6.主机模型属性分组 Return True Case RowNode.RowTypeEnum.ModelAttribute ' 7.主机模型属性 If String.IsNullOrEmpty(argRowNode.DeviceType) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = ":属性值为空,必须填入一个合法的属性值!" ErrCol = ColNames.DeviceType Return False Else Return True End If Case RowNode.RowTypeEnum.DeviceGroup ' 8.模型外设组 Return True Case RowNode.RowTypeEnum.DeviceObject ' 9.模型外设对象 If argRowNode.Lever = 4 AndAlso (argRowNode.Text = "设备:RS485A" OrElse argRowNode.Text = "设备:RS485P" OrElse argRowNode.Text = "端口:虚拟设备") Then Return True If String.IsNullOrEmpty(argRowNode.DeviceType) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Warning ErrMsg = argRowNode.Text & ":设备类型为空,只有指定类型的设备才能被正确配置!" ErrCol = ColNames.DeviceType Return False Else Return True End If Case RowNode.RowTypeEnum.DeviceAttributes ' 10.模型外设属性组 Return True Case RowNode.RowTypeEnum.DeviceMothods ' 11.模型外设方法组 Return True Case RowNode.RowTypeEnum.DeviceEvents ' 12.模型外设事件组 Return True Case RowNode.RowTypeEnum.DeviceAttribute ' 13.模型外设属性 If String.IsNullOrEmpty(argRowNode.DeviceType) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.Text & "属性为空,必须指定属性值!" ErrCol = ColNames.DeviceType Return False Else Return True End If Case RowNode.RowTypeEnum.DeviceMothod ' 14.模型外设方法 Return True Case RowNode.RowTypeEnum.DeviceEvent ' 15.模型外设事件 Return True Case RowNode.RowTypeEnum.DeviceEventActionModeGroup ' 16.模型外设事件动作执行方式组 Return True Case RowNode.RowTypeEnum.DeviceEventActionMode ' 17.模型外设事件动作执行方式 If String.IsNullOrEmpty(argRowNode.DeviceType) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.Text & "为空,必须指定动作执行方式!" ErrCol = ColNames.DeviceType Return False Else Return True End If Case RowNode.RowTypeEnum.DeviceEventConditionItem ' 18.模型外设事件条件 Return True Case RowNode.RowTypeEnum.DeviceEventAllConditions ' 19.模型外设事件条件 Return True Case RowNode.RowTypeEnum.DeviceEventConditions ' 20.条件组节点 If String.IsNullOrEmpty(argRowNode.DeviceType) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.Text & ":参数为空,必须指定动作执行条件!" ErrCol = ColNames.DeviceType Return False Else Return True End If Case RowNode.RowTypeEnum.DeviceEventAllActions ' 21.模型外设事件执行动作组集合 Return True Case RowNode.RowTypeEnum.DeviceEventActions ' 22.模型外设事件执行动作组 Return True Case RowNode.RowTypeEnum.DeviceEventAction ' 23.模型外设事件执行动作 If String.IsNullOrEmpty(argRowNode.DeviceType) AndAlso String.IsNullOrEmpty(argRowNode.DeviceName) Then Return True If String.IsNullOrEmpty(argRowNode.DeviceType) Then '设备类型’ ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.DeviceName & ":设备类型为空,必须指定设备类型!" ErrCol = ColNames.DeviceType Return False ElseIf String.IsNullOrEmpty(argRowNode.DeviceName) Then '设备名称’ ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.DeviceType & ":设备名称为空,必须指定设备名称!" ErrCol = ColNames.DeviceName Return False ElseIf String.IsNullOrEmpty(argRowNode.DelayTime) Then '执行时间 ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.DeviceName & ":执行时间为空,必须指定执行时间!" ErrCol = ColNames.DelayTime Return False ElseIf String.IsNullOrEmpty(argRowNode.DelayUnit) Then '执行时间单位 ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.DeviceName & ":执行时间单位为空,必须指定执行时间单位!" ErrCol = ColNames.DelayUnit Return False ElseIf argRowNode.DeviceType <> "动作组" And String.IsNullOrEmpty(argRowNode.DeviceMothed) Then '执行方法 ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.DeviceName & " : 设备方法为空,必须指定设备方法!" ErrCol = ColNames.DeviceMothed Return False Else Return True End If Case RowNode.RowTypeEnum.ContextualModels ' 24.情景模式组 Return True Case RowNode.RowTypeEnum.ContextualModel ' 25.情景模式 If String.IsNullOrEmpty(argRowNode.DeviceAlias) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Warning ErrMsg = argRowNode.Text & ":别名为空,没有指定别名就没办法被调用!" ErrCol = ColNames.DeviceAlias Return False Else Return True End If Case RowNode.RowTypeEnum.ExternalModel ' 26.外设模型 If String.IsNullOrEmpty(argRowNode.DeviceAlias) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Warning ErrMsg = argRowNode.Text & ":别名为空,建议为外设设定别名以方便调用!" ErrCol = ColNames.DeviceAlias Return False Else Return True End If Case RowNode.RowTypeEnum.ModelAttributes_XiaoBaoCMD '27.属性集 = XiaoBaoCMD Return True Case RowNode.RowTypeEnum.ModelAttribute_XiaoBaoCMD '28.属性 = XiaoBaoCMD Return True Case RowNode.RowTypeEnum.ModelAttributes_DeviceExists '29.属性集 = 设备存在 Return True Case RowNode.RowTypeEnum.ModelAttribute_DeviceExists '30.属性 = 设备存在 If String.IsNullOrEmpty(argRowNode.DeviceType) Then ErrType = RuleCheckErrTypeEnum.RuleCheck_Error ErrMsg = argRowNode.Text & ":参数为空,必须指定参数!" ErrCol = ColNames.DeviceType Return False Else Return True End If Case Else Return False End Select Return True End Function #End Region #Region "资源管理器方法" Private Sub rsmTreeViewSelectItem(argGridRowIdx As Integer) If argGridRowIdx < 1 OrElse argGridRowIdx > _grd.Rows - 1 Then Return Dim node As RowNode = FindRowNode(argGridRowIdx) Select Case node.RowType Case RowNode.RowTypeEnum.DeviceObject For Each rsmTreeNode As rsmTreeNode In _rsm_node_objectGroups.Nodes If node.RowListIndex = rsmTreeNode.rowNodeIdx Then '_rsm_node_objectGroups.SelectedImageIndex = rsmTreeNode.Index _tv.SelectedNode = CType(_rsm_node_objectGroups.Nodes(rsmTreeNode.Index), TreeNode) 'MsgBox("Bingo-" & rsmTreeNode.Index & "," & node.RowListIndex) End If Next End Select End Sub ''' ''' 为节点找到指定类型的父节点 ''' ''' ''' ''' ''' Private Function findFathersRowtype(ByVal argNode As RowNode, ByVal argRowType As RowNode.RowTypeEnum, ByRef argFathersRownode As RowNode) As Boolean If argNode.Lever < 2 Then Return False If argNode.RowListIndex < 1 OrElse argNode.RowListIndex > _grd.Rows - 1 Then Return False Dim node As RowNode = argNode While node.Lever > 2 If node.RowType = argRowType Then argFathersRownode = node Return True Else node = node.ParentNode End If End While Return False End Function ''' ''' 刷新资源管理器的所有列表,暴力全局刷新,效率不咋地,而且有点闪,有空再做个单条刷新 ''' Public Sub UpdateAllResourceList() _rsmObject.FillActionGroups() tvNodeClear() Dim tmpChildNodeUsedCnt As Integer = 0 Dim tmpRsmTNtext As String = "" '添加设备 'S1:清零键值对 _rsm_KeyPair_objectGroups.Clear() tmpChildNodeUsedCnt = 0 'S2:遍历设备组中的键值 For Each tmpStrKey As String In _rsmObject._objectGroups.Keys Dim tmpNode As RowNode = _rsmObject._objectGroups(tmpStrKey) '对应设备组中的节点’ Dim tmpTVnode As New rsmTreeNode '新建一个treeview节点’ tmpTVnode.Text = tmpNode.RowListIndex & " -(" & tmpNode.DeviceType & ")- " & tmpStrKey & "(" & tmpNode.Text & ")" '节点文字内容’ tmpTVnode.rowNodeIdx = tmpNode.RowListIndex '节点指向的rowNodeIdx,方便双击时导航到对应的表格行’ 'S3:匹配键值对所指向的设备有没有被调用’ If _rsmObject._objectWhereUsed.ContainsKey(tmpStrKey) Then Dim tmpChildNodeCnt As Integer = _rsmObject._objectWhereUsed(tmpStrKey).Count '调用缓存列表长度,0代表没有调用’ 'Console.WriteLine("tmpNodeList.Count = " & tmpChildNodeCnt If tmpChildNodeCnt > 0 Then 'S4:遍历列调用列表,将调用位置放到节点下,可双击导航到对应节点’ For Each node As RowNode In _rsmObject._objectWhereUsed(tmpStrKey) Dim tmpChileNode As New rsmTreeNode tmpChileNode.ImageKey = "01087.ico" tmpChileNode.rowNodeIdx = node.RowListIndex '为节点找到事件节点’ tmpRsmTNtext = "" Dim tmpFatherNode As New RowNode If findFathersRowtype(node, RowNode.RowTypeEnum.DeviceEvent, tmpFatherNode) = True Then tmpRsmTNtext = tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" '继续找对象节点 If findFathersRowtype(node, RowNode.RowTypeEnum.DeviceObject, tmpFatherNode) = True Then tmpRsmTNtext = tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" & "-" & tmpRsmTNtext End If ElseIf findFathersRowtype(node, RowNode.RowTypeEnum.ContextualModel, tmpFatherNode) = True Then '场景 tmpRsmTNtext = tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" End If '找不到事件和场景父节点,就直接找动作组父节点 If findFathersRowtype(node, RowNode.RowTypeEnum.DeviceEventActions, tmpFatherNode) = True Then tmpRsmTNtext = tmpRsmTNtext & " - " & tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" End If tmpChileNode.Text = node.RowListIndex & " - " & node.DeviceAlias & " : " & tmpRsmTNtext & " : " & node.DeviceMothed tmpChileNode.ForeColor = Color.Firebrick tmpTVnode.Nodes.Add(tmpChileNode) Next tmpTVnode.ForeColor = Color.Black tmpChildNodeUsedCnt += 1 Else tmpTVnode.ForeColor = Color.Silver End If tmpTVnode.ImageKey = GetDeviceTypeIcon(tmpNode, tmpChildNodeCnt) tmpTVnode.Text = tmpTVnode.Text & " (" & tmpChildNodeCnt & ")" End If 'S5:添加treeview节点,一个节点表示一个设备,设备下的子节点集合了调用改节点的行’ _rsm_node_objectGroups.Text = "设备" & " (" & tmpChildNodeUsedCnt & " / " & _rsm_node_objectGroups.Nodes.Count + 1 & ")" _rsm_node_objectGroups.Nodes.Add(tmpTVnode) '增加到键值对里面,貌似这个变量没啥用了,通过生成 rsmTreeNode 类 (继承了TreeNode类)来导航,先留着吧’ _rsm_KeyPair_objectGroups.Add(_rsm_node_objectGroups.LastNode.Index, tmpNode) Next '添加动作组 _rsm_KeyPair_actionGroups.Clear() tmpChildNodeUsedCnt = 0 For Each tmpStrKey As String In _rsmObject._actionGroups.Keys Dim tmpNode As RowNode = _rsmObject._actionGroups(tmpStrKey) Dim tmpTVnode As New rsmTreeNode tmpTVnode.Text = tmpNode.RowListIndex & " -(" & tmpNode.DeviceType & ")- " & tmpStrKey tmpTVnode.rowNodeIdx = tmpNode.RowListIndex If _rsmObject._actionGroupWhereUsed.ContainsKey(tmpStrKey) Then Dim tmpChildNodeCnt As Integer = _rsmObject._actionGroupWhereUsed(tmpStrKey).Count 'Console.WriteLine("tmpNodeList.Count = " & tmpChildNodeCnt If tmpChildNodeCnt > 0 Then For Each node As RowNode In _rsmObject._actionGroupWhereUsed(tmpStrKey) Dim tmpChileNode As New rsmTreeNode tmpChileNode.ImageKey = "01087.ico" tmpChileNode.rowNodeIdx = node.RowListIndex '为节点找到事件节点’ tmpRsmTNtext = "" Dim tmpFatherNode As New RowNode If findFathersRowtype(node, RowNode.RowTypeEnum.DeviceEvent, tmpFatherNode) = True Then tmpRsmTNtext = tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" '继续找对象节点 If findFathersRowtype(node, RowNode.RowTypeEnum.DeviceObject, tmpFatherNode) = True Then tmpRsmTNtext = tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" & "-" & tmpRsmTNtext End If Else '找不到事件父节点,就直接找动作组父节点 If findFathersRowtype(node, RowNode.RowTypeEnum.DeviceEventActions, tmpFatherNode) = True Then tmpRsmTNtext = tmpFatherNode.DeviceAlias & "(" & tmpFatherNode.Text & ")" End If End If tmpChileNode.Text = node.RowListIndex & " - " & node.DeviceAlias & " : " & tmpRsmTNtext & " : " & node.DeviceMothed tmpChileNode.ForeColor = Color.Firebrick tmpTVnode.Nodes.Add(tmpChileNode) Next tmpTVnode.ForeColor = Color.Black tmpChildNodeUsedCnt += 1 Else tmpTVnode.ForeColor = Color.Silver End If tmpTVnode.ImageKey = GetDeviceTypeIcon(tmpNode, tmpChildNodeCnt) tmpTVnode.Text = tmpTVnode.Text & " (" & tmpChildNodeCnt & ")" End If _rsm_node_actionGroups.Text = "动作组" & " (" & tmpChildNodeUsedCnt & " / " & _rsm_node_actionGroups.Nodes.Count + 1 & ")" _rsm_node_actionGroups.Nodes.Add(tmpTVnode) _rsm_KeyPair_actionGroups.Add(_rsm_node_actionGroups.LastNode.Index, tmpNode) Next '添加场景 _rsm_KeyPair_contextualGroups.Clear() tmpChildNodeUsedCnt = 0 For Each tmpStrKey As String In _rsmObject._contextualGroups.Keys Dim tmpNode As RowNode = _rsmObject._contextualGroups(tmpStrKey) Dim tmpTVnode As New rsmTreeNode tmpTVnode.Text = tmpNode.RowListIndex & " -(" & tmpNode.DeviceType & ")- " & tmpStrKey tmpTVnode.rowNodeIdx = tmpNode.RowListIndex If _rsmObject._contexualGroupsWhereUsed.ContainsKey(tmpStrKey) Then Dim tmpChildNodeCnt As Integer = _rsmObject._contexualGroupsWhereUsed(tmpStrKey).Count 'Console.WriteLine("tmpNodeList.Count = " & tmpChildNodeCnt If tmpChildNodeCnt > 0 Then For Each node As RowNode In _rsmObject._contexualGroupsWhereUsed(tmpStrKey) Dim tmpChileNode As New rsmTreeNode tmpChileNode.Text = node.RowListIndex & " - " & node.DeviceAlias & " : " & node.Text tmpChileNode.ImageKey = "01087.ico" tmpChileNode.rowNodeIdx = node.RowListIndex tmpTVnode.Nodes.Add(tmpChileNode) Next tmpTVnode.ForeColor = Color.Black tmpChildNodeUsedCnt += 1 Else tmpTVnode.ForeColor = Color.Silver End If tmpTVnode.ImageKey = GetDeviceTypeIcon(tmpNode, tmpChildNodeCnt) tmpTVnode.Text = tmpTVnode.Text & " (" & tmpChildNodeCnt & ")" End If _rsm_node_contextualGroups.Text = "场景" & " (" & tmpChildNodeUsedCnt & " / " & _rsm_node_contextualGroups.Nodes.Count + 1 & ")" _rsm_node_contextualGroups.Nodes.Add(tmpTVnode) _rsm_KeyPair_contextualGroups.Add(_rsm_node_contextualGroups.LastNode.Index, tmpNode) Next '添加小宝词条 _rsm_KeyPair_xiaobao.Clear() If _rsmObject._xiaobaoUsed.Count > 0 Then For Each tmpNode As RowNode In _rsmObject._xiaobaoUsed Dim tmpTVnode As New rsmTreeNode tmpTVnode.Text = tmpNode.RowListIndex & " -(" & tmpNode.Text & ")- " & tmpNode.DeviceType & " : " & tmpNode.DeviceName tmpTVnode.rowNodeIdx = tmpNode.RowListIndex _rsm_node_xiaobao.Nodes.Add(tmpTVnode) _rsm_KeyPair_xiaobao.Add(_rsm_node_xiaobao.LastNode.Index, tmpNode) Next End If _rsm_node_xiaobao.Text = "小宝词条" & " (" & _rsm_node_xiaobao.Nodes.Count + 1 & ")" _tv.ItemHeight = 18 _tv.Nodes.Clear() _tv.Nodes.Add(_rsm_rootNode) End Sub ''' ''' 展开资源管理器的treeview节点 ''' Public Sub ExpandTreeView() For Each tmptrnode As TreeNode In _tv.Nodes tmptrnode.Expand() For Each tmpChildNode As TreeNode In tmptrnode.Nodes tmpChildNode.Expand() Next Next End Sub ''' ''' 通过节点返回图标,图标根据节点的DeviceType而定,当子节点非0时返回彩色图标,否则返回单色图标 ''' ''' 节点 ''' 该节点的子节点数(用于确定返回单色或彩色图标) ''' 返回一个节点类型枚举 ''' Public Function GetDeviceTypeIcon(ByRef argNode As RowNode, ByVal argChildNodeCnt As Integer, Optional ByRef argDevTypeEnum As DeviceTypeEnum = DeviceTypeEnum.DeviceType_Others) As String If argNode Is Nothing Then Return "Others_gray" '现在图标不多,有时间补充一下图标的丰富程度’ Select Case argNode.DeviceType Case "KEY" argDevTypeEnum = DeviceTypeEnum.DeviceType_KEY If argChildNodeCnt > 0 Then Return "DI" Else Return "DI_gray" End If Case "PIR" argDevTypeEnum = DeviceTypeEnum.DeviceType_PIR If argChildNodeCnt > 0 Then Return "DI" Else Return "DI_gray" End If Case "DRY" argDevTypeEnum = DeviceTypeEnum.DeviceType_DRY If argChildNodeCnt > 0 Then Return "DI" Else Return "DI_gray" End If Case "TEMP" argDevTypeEnum = DeviceTypeEnum.DeviceType_TEMP If argChildNodeCnt > 0 Then Return "OTHERS" Else Return "Others_gray" End If Case "CARD" argDevTypeEnum = DeviceTypeEnum.DeviceType_CARD If argChildNodeCnt > 0 Then Return "DI" Else Return "DI_gray" End If Case "RELAY" argDevTypeEnum = DeviceTypeEnum.DeviceType_RELAY If argChildNodeCnt > 0 Then Return "RELAY" Else Return "RELAY_gray" End If Case "LIGHT" argDevTypeEnum = DeviceTypeEnum.DeviceType_LIGHT If argChildNodeCnt > 0 Then Return "PWM" Else Return "PWM_gray" End If Case "DIMMING" argDevTypeEnum = DeviceTypeEnum.DeviceType_DIMMING If argChildNodeCnt > 0 Then Return "OTHERS" Else Return "Others_gray" End If Case "MUSIC" argDevTypeEnum = DeviceTypeEnum.DeviceType_MUSIC If argChildNodeCnt > 0 Then Return "MUSIC" Else Return "MUSIC_gray" End If Case "CURTAIN" argDevTypeEnum = DeviceTypeEnum.DeviceType_CURTAIN If argChildNodeCnt > 0 Then Return "DOUT" Else Return "DOUT_gray" End If Case "INFRARED_FORWARD" argDevTypeEnum = DeviceTypeEnum.DeviceType_INFRARED_FORWARD If argChildNodeCnt > 0 Then Return "OTHERS" Else Return "Others_gray" End If Case "SERVICE" argDevTypeEnum = DeviceTypeEnum.DeviceType_SERVICE If argChildNodeCnt > 0 Then Return "OTHERS" Else Return "Others_gray" End If Case Else argDevTypeEnum = DeviceTypeEnum.DeviceType_Others If argChildNodeCnt > 0 Then Return "OTHERS" Else Return "Others_gray" End If End Select If argChildNodeCnt > 0 Then Return "OTHERS" Else Return "Others_gray" End If End Function #End Region #Region "输出打印" ''' ''' 编译打印 ''' ''' ''' Private Sub CompilePrint(sender As Object, e As OutputPrintEventArgs) RaiseEvent OutputPrint(sender, e) End Sub ''' ''' 输出对应类型信息 ''' ''' ''' Private Sub Print(type As OutputPrintEventArgs.Types, txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(type, txt)) End Sub ''' ''' 输出执行信息 ''' ''' Private Sub PrintInfo(txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Info, txt)) End Sub ''' ''' 输出警告信息 ''' ''' Private Sub PrintWarning(txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Warn, txt)) End Sub ''' ''' 输出错误信息 ''' ''' Private Sub PrintError(txt As String) RaiseEvent OutputPrint(Me, New OutputPrintEventArgs(OutputPrintEventArgs.Types.Error, txt)) End Sub Protected Overrides Sub Finalize() CreateErrHightTimer(False) '关闭错误单元格高亮时钟 MyBase.Finalize() End Sub #End Region #Region "打印调试信息" Dim gTimeLast As DateTime Public Sub DebugPrintTimeSpent(debugStr As String) Dim TimeNow As DateTime = Now Dim TimeDiff As TimeSpan = TimeNow - gTimeLast gTimeLast = TimeNow Console.WriteLine(TimeNow.ToString & " [" & TimeDiff.TotalMilliseconds.ToString & "]" & " : " & debugStr) End Sub #End Region Public Enum DeviceTypeEnum DeviceType_KEY DeviceType_PIR DeviceType_DRY DeviceType_CARD DeviceType_RELAY DeviceType_LIGHT DeviceType_MUSIC DeviceType_DIMMING DeviceType_CURTAIN DeviceType_INFRARED_FORWARD DeviceType_TEMP DeviceType_SERVICE DeviceType_Others End Enum ''' ''' 错误信息表格列明枚举 ''' Public Enum GridErrLstColNames fixedColume ID ErrType RowNodeIdx ErrMsg MAX End Enum ''' 表格列对应枚举 Public Enum ColNames ''' ''' 表格序号 ''' ID ''' ''' 是否启用 ''' Action ''' ''' 设备别名 ''' DeviceAlias ''' ''' 树状节点 ''' Node ''' ''' 设备类型 ''' DeviceType ''' ''' 设备名称 ''' DeviceName ''' ''' 设备方法 ''' DeviceMothed ''' ''' 执行延时 ''' DelayTime ''' ''' 延时单位 ''' DelayUnit ''' ''' 参数说明 ''' ParamDesc1 ''' ''' 参数数值 ''' ParamValue1 ''' ''' 参数说明 ''' ParamDesc2 ''' ''' 参数数值 ''' ParamValue2 ''' ''' 参数说明 ''' ParamDesc3 ''' ''' 参数数值 ''' ParamValue3 ''' ''' 参数说明 ''' ParamDesc4 ''' ''' 参数数值 ''' ParamValue4 ''' ''' 参数说明 ''' ParamDesc5 ''' ''' 参数数值 ''' ParamValue5 ''' ''' 参数说明 ''' ParamDesc6 ''' ''' 参数数值 ''' ParamValue6 ''' ''' 最大列数,不作为表格列名 ''' Max End Enum End Class 'RootNode ' 0.根节点 'HotelGroup ' 1.酒店组 'Hotel ' 2.酒店项目 'HotelRoomType ' 3.酒店户型 'Model ' 4.主机模型 'ModelAttributes ' 5.主机模型属性集 'ModelAttributeGroup ' 6.主机模型属性分组 'ModelAttribute ' 7.主机模型属性 'DeviceGroup ' 8.模型外设组 'DeviceObject ' 9.模型外设对象 'DeviceAttributes ' 10.模型外设属性组 'DeviceMothods ' 11.模型外设方法组 'DeviceEvents ' 12.模型外设事件组 'DeviceAttribute ' 13.模型外设属性 'DeviceMothod ' 14.模型外设方法 'DeviceEvent ' 15.模型外设事件 'DeviceEventActionModeGroup ' 16.模型外设事件动作执行方式组 'DeviceEventActionMode ' 17.模型外设事件动作执行方式 'DeviceEventConditionItem ' 18.模型外设事件条件 'DeviceEventAllConditions ' 19.模型外设事件条件 'DeviceEventConditions ' 20.条件组节点 'DeviceEventAllActions ' 21.模型外设事件执行动作组集合 'DeviceEventActions ' 22.模型外设事件执行动作组 'DeviceEventAction ' 23.模型外设事件执行动作 'ContextualModels ' 24.情景模式组 'ContextualModel ' 25.情景模式 'ExternalModel ' 26.外设模型 'ModelAttributes_XiaoBaoCMD '27.属性集 = XiaoBaoCMD 'ModelAttribute_XiaoBaoCMD '28.属性 = XiaoBaoCMD 'ModelAttributes_DeviceExists '29.属性集 = 设备存在 'ModelAttribute_DeviceExists '30.属性 = 设备存在 End Namespace