目录
[Map 3D开发实战系列] Map Resource Explorer 背景介绍--Kick off
[Map 3D开发实战系列] Map Resource Explorer 之二-- 运行和调试
[Map 3D开发实战系列] Map Resource Explorer 之三-- 添加AutoCAD风格的Palette界面
[Map 3D开发实战系列] Map Resource Explorer 之四-- Map3D开发中的WPF
[Map 3D开发实战系列] Map Resource Explorer 之五--界面设计
[Map 3D开发实战系列] Map Resource Explorer 之六--资源操作及数据绑定
这篇文章中峻祁连将给大家介绍如何获取资源内容的XML表示,这个功能在我们基于Map 3D开发过程中是经常需要用到的,了解的资源的具体XML表示的内容,能帮你更好的理解Map 3D中的资源,从而在开发过程中少走弯路。
在上一篇文章中我已经枚举出了Map 3D文档资源库中的所有资源,并按照资源的类型分类显示在TreeView中,现在我们来给这个TreeView加个右键菜单来实现对指定资源的相关操作。我们这里介绍两个最常用的操作,就是查看资源内容ResourceContent和查看资源的相互引用关系。
首先加一个右键菜单ContextMenu,并定义相关的Click事件。这里为了能使在TreeView上单击右键弹出上下文菜单的同时也能选择TreeViewItem,参考了TianFang的两篇博文的实现方法。具体你可以参考他的原文,连接如下:
http://www.cnblogs.com/TianFang/archive/2010/02/10/1667153.html
http://www.cnblogs.com/tianfang/archive/2010/02/10/1667186.html
修改后的XAML如下:
<UserControl x:Class="MapResourceExplorer.UI.ExplorerForm" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300"> <Grid> <TreeView Margin="12,44,12,20" Name="treeView1" PreviewMouseRightButtonDown="treeView1_PreviewMouseRightButtonDown"> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/> </Style> </TreeView.ItemContainerStyle> <TreeView.CommandBindings> </TreeView.CommandBindings> <TreeView.ContextMenu> <ContextMenu Name="ResOpMenu" ContextMenuOpening="ContextMenu_Opening"> <MenuItem Header="Show Resource Content" Click="ShowResourceContent_Clicked"/> <MenuItem Header="Show Resource References" Click="ShowResourceReferences_Clicked"/> </ContextMenu> </TreeView.ContextMenu> <TreeViewItem Header="FeatureSource" > <TreeViewItem Header="Library://1....." ToolTip="" ></TreeViewItem> </TreeViewItem> <TreeViewItem Header="Layer Definition"> <TreeViewItem Header="Library://1....."></TreeViewItem> </TreeViewItem> </TreeView> <ToolBar Height="26" Margin="12,12,12,0" Name="toolBar1" VerticalAlignment="Top" > <Button Name="Refresh" Click="RefreshButton_Clicked"> <Image Source="Images\refresh.gif" Height="16" Width="16"></Image> </Button> <Button Name="EditXml"> <Image Source="Images\edit-xml.png" Height="16" Width="16"></Image> </Button> <Button Name="About"> <Image Source="Images\about.png" Height="16" Width="16"></Image> </Button> <Button Name="Help"> <Image Source="Images\help.png" Height="16" Width="16"></Image> </Button> </ToolBar> </Grid> </UserControl>
准备工作做完了,就可以来实现右键菜单的执行逻辑了,为了显示资源内容(ResourceContent),我想应该用一个弹出窗口里面放个文本框来表示。于是我在Visual Studio 的目录下添加一个Windos Form,命名为XmlEditor.cs。在这个Windos Form里面拖一个TextBox空间进去,一个最简单的显示界面就算完成了。当然为了给这个窗体以后增加更丰富的功能,我还放了一个工具条在上面。然后在右键菜单项的Click事件中写实现函数。我不想把对资源操作的业务逻辑代码也混在界面相关的类中,所以我还是放在ResourceManager类中,调用代码就很简单了,传入一个要查询的资源ID,把以字符串形式返回的结果放在窗体的TextBox里面,然后把窗体显示出来就OK了。这里我还把当前操作的资源ID传给是显示窗体XmlEditor,这个是为以后使用做准备的,现在先不管他。
private void ShowResourceContent_Clicked(object sender, RoutedEventArgs e) { if (isResItemSlected) { TreeViewItem item = treeView1.SelectedItem as TreeViewItem; string resId = item.ToolTip.ToString(); string resXml = ResourceManager.Instance.GetResourceContent(resId); XmlEditor.Instance.CurrentResourceId = resId; XmlEditor.Instance.SetXml(resXml); XmlEditor.Instance.ShowDialog(); } }
private void ShowResourceReferences_Clicked(object sender, RoutedEventArgs e) { if (isResItemSlected) { TreeViewItem item = treeView1.SelectedItem as TreeViewItem; string resId = item.ToolTip.ToString(); string resXml = ResourceManager.Instance.GetResourceReferences(resId); XmlEditor.Instance.CurrentResourceId = resId; XmlEditor.Instance.SetXml(resXml); XmlEditor.Instance.ShowDialog(); } }
好,那现在我们到ResourceManager中来实现获取资源内容的GetResourceContent方法和查找引用关系的GetResourceReferences方法。其实也是非常简单的,只需要调用Map 3D Geospatial platform API中资源服务的相关方法就行了。在之前最好需要检查一下传入的资源ID是否正确,即调用MgResourceService::ResourceExists方法检查指定的资源是否存在,如果不存在就返回一个常量的错误信息字符串。MgResourceService::GetResourceContent的返回值是一个MgByteReader类型,里面包含了ResourceContent的XML表示,调用ToString()方法即可。
private MgResourceService _resourceService; public MgResourceService ResourceService { get { if (_resourceService == null) { _resourceService = AcMapServiceFactory.GetService(MgServiceType.ResourceService) as MgResourceService; } return _resourceService; } }
public string GetResourceContent(string resourceId) { MgResourceIdentifier resId = new MgResourceIdentifier(resourceId); if (ResourceService.ResourceExists(resId)) { MgByteReader reader = ResourceService.GetResourceContent(resId); return reader.ToString(); } else { return MSG_RESOURCE_NOT_EXIST; } } public string GetResourceReferences(string resourceId) { MgResourceIdentifier resId = new MgResourceIdentifier(resourceId); if (ResourceService.ResourceExists(resId)) { MgByteReader reader = ResourceService.EnumerateReferences(resId); return reader.ToString(); } else { return MSG_RESOURCE_NOT_EXIST; } }
好了,代码写完了,是不是很简单?运行一下看看效果,到要看看这些资源都是些什么东西。F5调试运行启动外部程序Map 3D或者Civil 3D,通过netload命令加载刚创建好的程序集。在测试之前我首先在Map 3D添加一些资源。打开 Map 3D,在Home选项卡中的Connect按钮,打开数据连接管理器,选择“Add SDF Connection”连接到一个SDF文件,你也可以连接到Oracle,SHP等等,然后点Connect按钮。这时候创建了一个FeatureSource的资源。
在后续的对话框中选中feature class点“Add to Map”来添加到地图。这时会创建对应的图层,生成LayerDefiniation类型的资源。
数据准备完成了,现在该调出我们编写的ResourceExplorer来测试一下了,资源树中果然显示出了两个资源。
现在首先在SDF_1这个要素源上点右键查看他的ResourceContent。返回的结果XML将显示在一个弹出窗体中,如果你仔细分析一下这个XML就会发现这也只是定义了一个到SDF文件的连接而已。好了,如果你有Oracle数据库的连接资源,也可以来看看他内部是什么样的了,其实也不过就是些连接定义罢了。同样你也可以查看LayerDefiniation资源的ResourceContent,无非也就是到FeatureSource的连接和对图层样式等信息的一些定义,您可以自己慢慢来分析一下。
好了,今天先写到这里。到此为止,我们的ResourceExplorer已经算是基本完成了。后续我还会加上资源修改的功能。
完整代码可以从Google Code上下载: http://code.google.com/p/map-resource-explorer/ 如果你发现什么bug,欢迎给我反馈,更欢迎你能加入一起修改完善 :)
Cheers,
峻祁连