/// <summary> /// 修改节点树(添加节点,删除节点,修改节点名称) /// </summary> /// <param name="nodes"></param> public void UpdateNodesAttribute(List <OpcuaNode> nodes) { //修改或创建根节点 var scadas = nodes.Where(d => d.NodeType == NodeType.Scada); foreach (var item in scadas) { FolderState scadaNode = null; if (!_folderDic.TryGetValue(item.NodePath, out scadaNode)) { //如果根节点都不存在 那么整个树都需要创建 FolderState root = CreateFolder(null, item.NodePath, item.NodeName); root.AddReference(ReferenceTypes.Organizes, true, ObjectIds.ObjectsFolder); _references.Add(new NodeStateReference(ReferenceTypes.Organizes, false, root.NodeId)); root.EventNotifier = EventNotifiers.SubscribeToEvents; AddRootNotifier(root); CreateNodes(nodes, root, item.NodePath); _folderDic.Add(item.NodePath, root); AddPredefinedNode(SystemContext, root); continue; } else { scadaNode.DisplayName = item.NodeName; scadaNode.ClearChangeMasks(SystemContext, false); } } //修改或创建目录(此处设计为可以有多级目录,上面是演示数据,所以我只写了三级,事实上更多级也是可以的) var folders = nodes.Where(d => d.NodeType != NodeType.Scada && !d.IsTerminal); foreach (var item in folders) { FolderState folder = null; if (!_folderDic.TryGetValue(item.NodePath, out folder)) { var par = GetParentFolderState(nodes, item); folder = CreateFolder(par, item.NodePath, item.NodeName); AddPredefinedNode(SystemContext, folder); par.ClearChangeMasks(SystemContext, false); _folderDic.Add(item.NodePath, folder); } else { folder.DisplayName = item.NodeName; folder.ClearChangeMasks(SystemContext, false); } } //修改或创建测点 //这里我的数据结构采用IsTerminal来代表是否是测点 实际业务中可能需要根据自身需要调整 var paras = nodes.Where(d => d.IsTerminal); foreach (var item in paras) { BaseDataVariableState node = null; if (_nodeDic.TryGetValue(item.NodeId.ToString(), out node)) { node.DisplayName = item.NodeName; node.Timestamp = DateTime.Now; node.ClearChangeMasks(SystemContext, false); } else { FolderState folder = null; if (_folderDic.TryGetValue(item.ParentPath, out folder)) { node = CreateVariable(folder, item.NodePath, item.NodeName, DataTypeIds.Double, ValueRanks.Scalar); AddPredefinedNode(SystemContext, node); folder.ClearChangeMasks(SystemContext, false); _nodeDic.Add(item.NodeId.ToString(), node); } } } /* * 将新获取到的菜单列表与原列表对比 * 如果新菜单列表中不包含原有的菜单 * 则说明这个菜单被删除了 这里也需要删除 */ List <string> folderPath = _folderDic.Keys.ToList(); List <string> nodePath = _nodeDic.Keys.ToList(); var remNode = nodePath.Except(nodes.Where(d => d.IsTerminal).Select(d => d.NodeId.ToString())); foreach (var str in remNode) { BaseDataVariableState node = null; if (_nodeDic.TryGetValue(str, out node)) { var parent = node.Parent; parent.RemoveChild(node); _nodeDic.Remove(str); } } var remFolder = folderPath.Except(nodes.Where(d => !d.IsTerminal).Select(d => d.NodePath)); foreach (string str in remFolder) { FolderState folder = null; if (_folderDic.TryGetValue(str, out folder)) { var parent = folder.Parent; if (parent != null) { parent.RemoveChild(folder); _folderDic.Remove(str); } else { RemoveRootNotifier(folder); RemovePredefinedNode(SystemContext, folder, new List <LocalReference>()); } } } }