原文地址http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-cnfext2/index.html
扩展 project explorer 视图支持 XML 模型结构,第 1部分
http://blog.csdn.net/andywangcn/article/details/8258094
CNF 菜单扩展及 XML 文档操作
简介: CNF(Common Navigator Framework)是一个通用的、可扩展的导航视图框架。通过 CNF,开发人员很容易开发一个 CNF 视图,或者对已有的CNF视图进行扩展。这篇文章主要介绍如何利用 CNF 框架扩展现有的 CNF 视图 Project Explorer,使其能够展示 XML 文件的文档结构,并且支持对 XML 元素的菜单操作。文章分为上下两篇,第一篇介绍如何基于 CNF 框架扩展现有的 CNF 视图 Project Explorer,使其支持XML文件的文档结构展示。其中涉及一系列的 CNF 扩展点,XML 文档模型及其解析等内容。第二篇介绍稍微高级一些的内容,介绍如何基于 CNF 框架定制 CNF 视图菜单,如何基于 CNF 菜单对 XML 模型进行操作,以及如何同步更新等内容。通过这篇文章,读者可以对 CNF 框架,以及如何使用 CNF 框架展示并操作 XML 文档结构有深入的了解。
发布日期: 2008 年 1 月 17 日
访问情况 : 1956 次浏览
评论:
除了在 CNF 视图中支持 XML 文档结构的展示,一些用户还希望能够在 CNF 视图中对 XML 文档模型进行操作,让其支持一系列的右键菜单,并通过菜单操作对 XML 文档进行操作。如何实现这种需求呢? CNF 框架提供了菜单相关的扩展点,让用户能够定义 CNF 视图中节点的右键菜单结构和菜单操作。
文章例子实现了两类菜单:
一类是普通的视图菜单,文章中的例子对 XML 文档结构进行展示,但并非对所有的 XML 文档都可以进行展示 ,而是有选择的进行展示,该 XML 文档的头结点的名称空间必须符合一定要求,才能够被解析并展示。这个菜单是针对 XML 文档的菜单操作,使得能自动的把一个不符合本文展示要求的XML文档转换为符合要求的 XML 文档。菜单效果图如下图左边所示:
另一类是通过 CNF 框架扩展菜单,这些菜单对 XML 文档展示的树型节点进行操作,比如打开操作,删除操作等。这些菜单只有 XML 文档展示的树型节点才具有。如下图所示:
图 1. 菜单效果图
![菜单效果图](https://i-blog.csdnimg.cn/blog_migrate/29ad7bd7e399bddd619fa9b2f214b770.png)
菜单操作涉及到对 XML 模型的操作,对 XML 编辑器的操作,以及如何更新同步 XML 模型、 XML 编辑器和 XML 树型结构视图。这一系列的知识点以及技术细节在接下来的几节将一一介绍
CNF 框架提供菜单扩展的机制,允许定制 CNF 视图的右键菜单支持。实现 CNF 菜单扩展需要两个步骤,一是定义右键菜单的菜单结构,二是定义菜单结构中展示的菜单项和操作。这一节介绍第一步骤,即如何定义菜单的结构。
CNF 框架提供了两种方法支持配置右键菜单结构。下面分别介绍这两种方法:
第一种方法比较简单,只需要定义在 “org.eclipse.ui.navigator.viewer” 扩展点中的 <viewer /> 节点的 popupMenuId 属性的值,这样菜单结构采用默认的右键菜单结构。如果 popupMenuId 属性没有赋值,则默认采用 viewerId 的值。下面是采用第一种方法时的菜单定义:
代码列表 1. 定义 popupMenuId 属性的值
<extension point="org.eclipse.ui.navigator.viewer"> <viewer popupMenuId="com.ibm.developerwork.xmlnavigator.popupMenuId" viewerId="org.eclipse.ui.navigator.ProjectExplorer"/> |
这种情况下, CNF 视图菜单结构就是默认的,默认菜单组名称及顺序如下所示:
代码列表 2. CNF 视图默认菜单组名称及顺序
"group.new" separator="true" "group.goto" "group.open" separator="true" "group.openWith" "group.show" separator="true" "group.edit" separator="true" "group.reorganize" "group.port" "group.generate" separator="true" "group.search" separator="true" "group.build" separator="true" "additions" separator="true" "group.properties" separator="true" |
这些值能够被 org.eclipse.ui.popupMenus 扩展点中菜单中的 menubarPath 属性引用,表明该菜单是显示在上面定义的菜单结构中。所有的这些默认的菜单结构值在 org.eclipse.ui.navigator.ICommonMenuConstants 中都定义了常量,方便用户在开发过程中用到。
第二种方法复杂一些,但也比较灵活,允许用户通过扩展点定义菜单的结构。这两种方法不能同时配置,本文的例子采用的是第二种方法。可以通过在定义 <viewer/> 下定义 <popupMenu/> 元素来定义该 CNF 视图支持的菜单结构,我们可以定义任意的菜单结构。可以通过 Manifest Plug-in Editor 的扩展点选项页来定义菜单结构,具体方法很简单,就不进行演示。我们例子中的菜单结构定义和 Project Explorer 一样的菜单结构,如下所示:
代码列表 3. 自定义菜单结构
<extension point="org.eclipse.ui.navigator.viewer"> <viewer viewerId="org.eclipse.ui.navigator.ProjectExplorer"> <popupMenu allowsPlatformContributions="false" id="org.eclipse.ui.examples.navigator.view#PopupMenu"> <insertionPoint name="group.new"/> <insertionPoint name="group.open" separator="true"/> <insertionPoint name="group.openWith"/> <insertionPoint name="group.edit" separator="true"/> <insertionPoint name="group.reorganize" /> <insertionPoint name="group.port" separator="true"/> <insertionPoint name="group.build" separator="true"/> <insertionPoint name="group.generate" separator="true"/> <insertionPoint name="group.search" separator="true"/> <insertionPoint name="additions" separator="true"/> <insertionPoint name="group.properties" separator="true"/> </popupMenu> </viewer> |
我们对上面的菜单结构定义进行解释:
- <insertionPoint/> 元素表示一个菜单组
- Separator 表示菜单组之间是否用一个水平线进行分割,如果值为真 (true) ,则表示菜单组之间有水平线分割,如果为假,则相反。如果相隔的两个菜单组都设置了分割栏,Eclipse 只显示一个。
- allowsPlatformContributions 表示是否接受 popupMenus 扩展点定义的菜单,如果设置为真,则 popupMenus 扩展点定义的菜单以及 ActionProvider 定义的菜单都可以在菜单结构中显示;如果设置假,则 popupMenus 扩展点定义的菜单不能在菜单结构中显示,只有 ActionProvider 定义的菜单才予以显示。
定义好 CNF 视图菜单结构以后,需要定义相应的菜单项,以及菜单项对应的操作,这一节主要介绍如何向菜单结构中添加菜单项,具体菜单项的实现类即如何操作 XML 模型将在下一节介绍。有两种方法可以向 CNF 视图添加菜单项。文章的例子中定义了两个 CNF 菜单项,每个菜单项用到其中一种方法,用于向用户展现这两种方法的用法。
第一种方法是利用 org.eclipse.ui.popupMenus 扩展点,该扩展点允许用户在Eclipse全局范围内扩展操作(action),并且经过配置能够在 CNF 视图中展示菜单项。文章例子中的删除 XML 节点操作 DeleteElementAction 就是通过这种方法实现。下面是 DeleteElementAction 的定义:
代码列表 3. DeleteElementAction 的定义
<extension point="org.eclipse.ui.popupMenus"> <objectContribution adaptable="false" id="com.ibm.developerwork.xmlnavigator.action.deleteaction" objectClass="org.eclipse.wst.xml.core.internal.document.ElementImpl"> <action class="com.ibm.developerwork.xmlnavigator.action.DeleteElementAction" enablesFor="1" helpContextId="org.eclipse.ui.edit.delete" icon="icons/delete_obj.gif" id="com.ibm.developerwork.xmlnavigator.action.DeleteElementAction" label="Delete Element" menubarPath="group.edit" tooltip="Delete a specific XML element"/> </objectContribution> </extension> |
下面解释该菜单项定义:
- 上面的菜单定义定义了菜单的标题(label),菜单图标(icon),工具提示(tooltip)。
- menubarPath 填写菜单结构中定义的菜单组的 Id,group.edit 表示该菜单显示在这个菜单组中。菜单组在上一节的菜单结构中已经定义好了。
- objectClass 属性定义了 CNF 视图中什么样的节点才能显示该菜单,这里的 ElementImpl 类表示只有右键选中的是 XML 模型中的 XML 子节点时,才能显示该菜单。
- class 属性是菜单的业务逻辑实现类,这个类必须是 org.eclipse.ui.actions.ActionDelegate 类的子类。这个类中的重载 run(IAction) 方法和 selectionChanged(IAction, ISelection) 是主要业务逻辑实现的方法,这个类只有当菜单被用户选中执行时才会被装载,并运行相应的业务逻辑。我们在下一小节将详细介绍这个类。
第二种方法是使用 org.eclipse.ui.navigator.navigatorContent 扩展点的 acitonProviders 元素。文章例子中的 OpenElementAction 菜单就是通过这种方法展现。这种方法是通过代码的方式向 CNF 视图中添加菜单项。当用户想在决定显示哪些菜单项之前做一些逻辑判断的时候,这种方法比较有用。下面是本文例子中 org.eclipse.ui.navigator.navigatorContent 中 acitonProviders 的定义:
代码列表 4. acitonProviders 的定义
<extension point="org.eclipse.ui.navigator.navigatorContent"> <navigatorContent activeByDefault="true" contentProvider="com.ibm.developerwork.xmlnavigator.XMLViewContentProvider" id="com.ibm.developerwork.xmlnavigator.xmlcontent" labelProvider="com.ibm.developerwork.xmlnavigator.XMLViewLabelProvider" name="XML Content" icon="icons/sample.gif" priority="normal"> <triggerPoints> <and> <instanceof value="org.eclipse.core.resources.IResource"/> <test forcePluginActivation="true" property="com.ibm.developerwork.namespace" value="http://www.ibm.com/developerwork"/> </and> </triggerPoints> <possibleChildren> <instanceof value="org.eclipse.wst.xml.core.internal.document.ElementImpl"/> </possibleChildren> <actionProvider class="com.ibm.developerwork.xmlnavigator.XMLContentActionProvider" id="com.ibm.developerwork.xmlnavigator.xmlcontentactionprovider"/> </navigatorContent> </extension> |
我们在 navigatorContent 扩展点下定义 actionProvider 元素,当 navigatorContent 通过 viewerContentBinding 帮定到 CNF 视图时,这里定义的 actionProvider 就做用于该 CNF 视图。另外我们也可以通过在 org.eclipse.ui.navigator.viewer 扩展点下面定义 viewerActionBinding 元素来绑定CNF视图和操作提供器(Action Provider),下面是本文例子中的定义:
代码列表 5. 绑定 CNF 视图和操作提供器
<viewerContentBinding viewerId="org.eclipse.ui.navigator.ProjectExplorer"> <includes> <contentExtension pattern="com.ibm.developerwork.xmlnavigator.xmlcontent"/> </includes> </viewerContentBinding> <viewerActionBinding viewerId="org.eclipse.ui.navigator.ProjectExplorer"> <includes> <actionExtension pattern="com.ibm.developerwork.xmlnavigator.xmlcontentactionprovider"/> </includes> </viewerActionBinding> |
actionProvider 中的 class 属性是操作提供器(action provider)类,本文例子中为 XMLContentActionProvier,该类继承 CommonActionProvider 类,并实现了三个方法,这三个方法是这个类的主要逻辑实现,分别如下所示:
init(ICommonActionExtensionSite aSite) 方法,该方法创建 OpenElementAction 菜单操作实例,除此外还作了一些其他工作,具体参见相应 Java API 文档。
代码列表 6. init 方法
public void init(ICommonActionExtensionSite aSite) { ICommonViewerSite viewSite = aSite.getViewSite(); if (viewSite instanceof ICommonViewerWorkbenchSite) { ICommonViewerWorkbenchSite workbenchSite = (ICommonViewerWorkbenchSite) viewSite; //创建OpenElementAction菜单操作实例 openAction = new OpenElementAction(workbenchSite.getPage(), workbenchSite.getSelectionProvider()); } } |
fillActionBars(IActionBars actionBars) 方法,这个方法用于配置可重定位操作(retargetable action)。
代码列表 7. fillActionBars 方法
public void fillActionBars(IActionBars actionBars) { if (openAction.isEnabled()) actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN,openAction); } |
fillContextMenu(IMenuManager menu) 方法,这个方用于展示菜单项在菜单结构中。ICommonMenuConstants.GROUP_OPEN 就是之前定义的菜单结构中的 group.open 菜单组。
代码列表 8. fillContextMenu 方法
public void fillContextMenu(IMenuManager menu) { // 如 果 openAction菜 单可 以 被 展 示 并 执行 if (openAction.isEnabled()) //添加openAction到展示菜单的group.open菜单组中 menu.appendToGroup(ICommonMenuConstants.GROUP_OPEN, openAction); } |
上面两个小节介绍了如何添加 CNF 视图菜单,这一节介绍三个菜单操作实现。这三个菜单操作都是对 XML 模型的操作,其中前面两个是上一节介绍的两个菜单的业务逻辑实现类,最后一个介绍如何把一个普通 XML 文档转换成本文的 XML 内容扩展可以识别的 XML 文档,即能够在 Project Explorer 中被展开的 XML 文档。
删除 XML 节点菜单实现,上节定义的删除 XML 节点的菜单,用于从 XML 文档中删除选中的 XML 节点。其菜单的具体业务逻辑实现类为 DeleteElementAction 类,它继承 ActionDelegate 类并且重载了 selectionChanged(IAction, ISelection) 方法和 run(IAction) 方法。selectionChanged 方法每次在选中视图中的节点时被调用,用于更新在视图中选中的节点,使得程序知道当前哪个节点被选中。该方法代码如下所示:
代码列表 9. selectionChanged 方法
public void selectionChanged(IAction action, ISelection sel) { if (sel instanceof IStructuredSelection) { selection = (IStructuredSelection) sel; if (!selection.isEmpty()) { IStructuredSelection sSelection = (IStructuredSelection) selection; if (sSelection.size() == 1 && sSelection.getFirstElement() instanceof ElementImpl) { data = ((ElementImpl) sSelection.getFirstElement()); } } } else selection = StructuredSelection.EMPTY; } |
DeleteElementAction 类重载的 run(IAction) 方法用于删除选中的 XML 节点。该方法中,首先得到 CNF 视图中被选中的 XML 节点在该 XML 文档中的位置,然后重新装载该 XML 模型,并且在新模型中查找刚才得到的 XML 节点的位置并且得到相应的 XML 节点,然后在新装载的 XML 模型中删除该节点,最后保存删除后的 XML 模型到文件系统。具体实现的代码如下所示:
代码列表 10. run 方法
//被选中的XML节点的模型 IDOMModel domModel = data.getModel(); //根据模型得到该XML文档的位置 String uri = domModel.getBaseLocation(); //通过位置得到该XML文档的IFile实例 IFile file = Helper.getFile(uri); //重新装载XML模型 IDOMModel model = Helper.getModelForResource(file); //得到被选中的XML节点的在整个XML文档中的位置 int offset = data.getStartOffset(); //在新装载的模型中得到被选中的XML节点 IndexedRegion region = model.getIndexedRegion(offset); if (region instanceof Node) { //在新装载的XML模型中删除被选中的XML节点,并且保存XML模型到XML文档文件中 Node node = (Node) region; node.getParentNode().removeChild(node); model.save(); } model.releaseFromRead(); domModel.releaseFromRead(); |
展开 XML 节点菜单实现,上节定义的在 XML 编辑器中展开 XML 节点的菜单,实现了在 XML 编辑器中打开该 XML 文档,并且在 XML 编辑器中高亮显示右键选中的 XML 节点,XML 编辑器中光标移动到这个 XML 节点上。其菜单的具体业务逻辑实现类为 OpenElementAction 类,它继承 org.eclipse.jface.action.Action 类,它实现了 OpenElementAction(IWorkbenchPage p, ISelectionProvider selectionProvider) 构造函数并且重载了 isEnabled() 方法和 run() 方法。
OpenElementAction(IWorkbenchPage p, ISelectionProvider selectionProvider) 构造函数用于设置菜单标题、图标、设置 ISelectionProvider 用于得到 CNF 视图中被选中的 XML 节点等。代码如下所示:
代码列表 11. OpenElementAction 方法
public OpenElementAction(IWorkbenchPage p, ISelectionProvider selectionProvider) { //设置菜单标题 setText("Open Element"); //$NON-NLS-1$ //设置IWorkbenchPage page = p; //设置ISelectionProvider用于得到CNF视图中被选中的XML节点等 provider = selectionProvider; } |
isEnabled() 方法用于判断这个菜单何时才能被展示,这里是只有当右键选中的 CNF 视图上的节点为 ElementImpl 实例,即 XML 节点实例时该菜单项才会被展示。
代码列表 12. isEnabled 方法
public boolean isEnabled() { //通过选择提供器,得到当前在CNF视图中选中的节点 ISelection selection = provider.getSelection(); if (!selection.isEmpty()) { IStructuredSelection sSelection = (IStructuredSelection) selection; //判断选中的节点是否为XML文档节点 if (sSelection.size() == 1 && sSelection.getFirstElement() instanceof ElementImpl) { //如果选中的是XML文档节点,则显示此菜单 data = ((ElementImpl) sSelection.getFirstElement()); return true; } } return false; } |
run() 方法执行真正的打开 XML 文档节点的操作。此操作用 XML 编辑器打开选中的 XML 节点所在的 XML 文档,然后在 XML 编辑器中把光标移到右键选中的 XML 节点上,并且高亮选中该 XML 节点。代码如下所示:
代码列表 13. run 方法
//根据选中的XML节点得到该节点所在的XML文档的模型 IDOMModel domModel = data.getModel(); //得到XML文档的路径 String uri = domModel.getBaseLocation(); //根据路径得到XML文档的IFile实例 IFile file = Helper.getFile(uri); //用默认的编辑器即XML编辑器打开XML文档 IEditorPart editor = IDE.openEditor(page, file); //把光标移到右键选中的XML节点上,并且高亮显示该节点 XMLMultiPageEditorPart xmlEditor = (XMLMultiPageEditorPart) editor; TextEditor textEditor = (TextEditor) xmlEditor.getAdapter(TextEditor.class); int start = data.getStartOffset(); int length = data.getLength(); textEditor.selectAndReveal(data.getStartOffset(), data.getLength()); textEditor.setHighlightRange(start, length, true); |
最后一个需要介绍的菜单操作是如何把一个普通 XML 文档转换成本文 XML 内容扩展可以识别的 XML 文档,即能够在 Project Explorer 中被展开的 XML 文档。我们知道只有当一个 XML 文档的头节点的名称空间为http://www.ibm.com/developerwork 时,该 XML 文档才能被本文例子中定义的 XML 内容扩展解析并展示在 CNF 视图中。下面是该菜单操作的定义:
代码列表 14. 定义菜单扩展
<extension point="org.eclipse.ui.popupMenus"> <objectContribution id="org.eclipse.ui.articles.action.contribution.popup.object" objectClass="org.eclipse.core.resources.IFile" nameFilter="*.xml"> <action id="com.ibm.developerwork.xmlnavigator.action.ChangeToDeveloperWorkerNSAction" label="Enable Developerwork Namespace" icon="icons/sample.gif" menubarPath="additions" class="com.ibm.developerwork.xmlnavigator.action.ChangeToDeveloperWorkerNSAction"> </action> </objectContribution> </extension> |
从定义中可以看出,只有当右键点击后缀为 XML 的文件时,该菜单才会被展示。该菜单的标题为 “Enable Developerwork Namespace”,菜单项的图标为 icons/sample.gif,该菜单展示在 Project Explorer 定义的 additions 菜单组中。最重要的是菜单类为 ChangeToDeveloperWorkerNSAction,该菜单继承 ActionDelegate 类,并重载了 run()方法。Run() 方法中对右键选中的 XML 文档进行解析,并把该文档的头元素的名称空间设为http://www.ibm.com/developerwork。Run() 代码如下所示:
代码列表 15. Run 方法
if (action instanceof ObjectPluginAction) { ObjectPluginAction action1 = (ObjectPluginAction) action; ISelection selection = action1.getSelection(); if (selection instanceof TreeSelection) { TreeSelection treeSel = (TreeSelection) selection; Object obj = treeSel.getFirstElement(); //设置选中的XML文档的名称空间 Helper.enableDeveloperworkNamespace((IFile) obj); } } |
文章中的例子涉及到了对 XML 文档模型的操作,比如 CNF 视图中的删除 XML 文档节点操作。另外用户可以通过 XML 编辑器打开 XML 文档,并在 XML 编辑器中编辑 XML 文档内容,这样的话,如何同步 Project Explorer CNF 视图和 XML 编辑器?如何在 Project Explorer CNF 视图中更新并展示最新的 XML 文档结构?文章例子采用了资源监听器 (IResourceChangeListener) 实现了同步更新。
文章例子中的 XML 内容提供类 XMLViewContentProvider 实现了 IResourceChangeListener 和 IResourceDeltaVisitor 接口。并且在该类的构造函数中启动了资源监听器,构造函数代码如下所示:
代码列表 16. XMLViewContentProvider 构造方法
public XMLViewContentProvider() { super(); //加载资源监听器,每当资源的删除,创建,修改操作都会触发此资源监听器 ResourcesPlugin.getWorkspace().addResourceChangeListener( this,IResourceChangeEvent.POST_CHANGE); } |
当资源发生变化后,资源监听器被调用,最终的业务代码在 visit(IResourceDelta delta) 方法中实现。在该方法中,刷新 Project Explorer CNF 视图,刷新的时候装载最新的 XML 模型,并展示在视图中。需要注意的是,例子中刷新后,维持 Project Explorer CNF 视图中的展开状态,具体的实现代码参见 Helper.refreshXML() 方法。visit(IResourceDelta delta) 方法代码如下所示:
代码列表 17. visit 方法
public boolean visit(IResourceDelta delta) throws CoreException { IResource changedResource = delta.getResource(); if (changedResource.getType() == IResource.FILE && changedResource.getFileExtension().equals("xml")) { final IFile file = (IFile) changedResource; //得到Project Explorer CNF视图实例 CommonViewer viewer = Helper.getProjectExplorerView(); if (null != viewer) { //刷新视图实例,进行刷新的时候,维持CNF树形的展开状态 Helper.refreshXML((CommonViewer) viewer); } return false; } return true; } |
这一小节主要介绍如何查看插件运行结果,本文例子的开发和运行环境都必须是Eclipse3.2以上。按照下列几个步骤验证本文例子实现的效果。
步骤一,按文章下面的地址下载插件,并运行插件。
步骤二,在运行Eclipse平台上,创建Java项目,项目名称设置为:test。切换到J2EE Perspective。
步骤三,在test项目中,创建一XML文件,文件名称为:test.xml。在该文件中输入下列内容:
代码列表 17. test.xml 内容
<?xml version="1.0" encoding="UTF-8"?> <root> <element id="element1" /> <element id="element2" /> </root> |
我们发现,J2EE Perspective的Project Explorer CNF视图并不展示此XML文档结构。
图 2. 扩展前的 Project Explorer 视图
![扩展前的 Project Explorer 视图](https://i-blog.csdnimg.cn/blog_migrate/ee1b65dc70b03510cc6318377cb6317d.png)
步骤四,右键选中 test.xml 文件,并运行菜单“Enable Developerwork Namespace”,此菜单的业务功能上面章节中有介绍。运行此菜单后,Project Explorer CNF 视图能够展示 test.xml 文档结构,如下图所示:
图 3. 扩展后的Project Explorer视图
![扩展后的Project Explorer视图](https://i-blog.csdnimg.cn/blog_migrate/fe173e98daf5fd735dcbfa49b82792cf.png)
步骤五,在 XML 编辑器中,添加 <element id=”element3”/>XML 节点,然后保存,保存后可以发现,左边的 Project Explorer 中的 text.xml 文档结构也相应更新,达到同步更新的效果。
步骤六,在左边的 Project Explorer 中的 text.xml 文档结构中,右键选中 element1=element.id 节点,然后选择 “Delete Element” 菜单项,如下图所示:
图 4. “Delete Element” 菜单项
![“Delete Element” 菜单项](https://i-blog.csdnimg.cn/blog_migrate/7b627a0feed4fdfe99025b34d99b18d3.png)
菜单项执行后,左边 Project Explorer CNF 视图和右侧的 XML 编辑器中的 XML 文档内容,同时发生更新变化,变化后结果如下图所示。此操作支持“Undo”,“Redo”。
图 5. “Delete Element” 菜单执行后截图
![“Delete Element” 菜单执行后截图](https://i-blog.csdnimg.cn/blog_migrate/ca72f26d933eb1871d9797d2e0c1f3b4.png)
步骤七,关闭 XML 编辑器,如下图所示:
图 6. 关闭 XML 编辑器后截图
![关闭 XML 编辑器后截图](https://i-blog.csdnimg.cn/blog_migrate/753a461c9c06f4f8ca71d18f17645395.png)
右键选中 “element3=element.id” XML 节点,然后选择“Open Element” 菜单。如下图所示:
图 7. “Open Element” 菜单执行后截图
![“Open Element” 菜单执行后截图](https://i-blog.csdnimg.cn/blog_migrate/2b526e24fc4b617d57628f7869648876.png)
菜单项执行后,XML 编辑器会自动打开,并且在 XML 编辑器中光标会移动到 “element3=element.id” XML 节点上,并且该节点呈选中状态。效果如下图所示:
图 8. “Open Element” 菜单项执行后截图
![“Open Element” 菜单项执行后截图](https://i-blog.csdnimg.cn/blog_migrate/de6213963b3f4e6839cff772d7f0a3dd.png)
通过第二篇文章,介绍了如何基于 CNF 框架定制导航视图菜单,如何基于 CNF 菜单对 XML 模型进行操作,以及如何同步更新。
描述 | 名字 | 大小 | 下载方法 |
---|---|---|---|
本文用到的示例代码 | xmlnavigator.zip | 34KB | HTTP |