论GIS应用程序开发的CBD开发策略--制作MapXtreme 瘦控件【转载】
2011-11-21 13:52
190 查看
CBD(Component Based Development)的开发方法,就是要以控件作为软件组装的基本单位,而不是以函数、过程、类作
为软件组装的基本单位。所以在Winform的GIS开发中,如果仅仅把MapXtreme控件放进窗体,然后在这个窗体上添加所有
GIS的操作的代码,那么很快就会发现这个应用程序变得腐朽(corrupt)而不可维护。软件的坏味道(bad smell)来自封装程度
不足。
胖控件,就是指把大部分的计算工作都交给Map控件来完成,例如专题图的划分范围颜色配置,图元的距离,最短路径等;
MapXtreme实现这些功能也许很直接,却未必是最高效的。把计算放在控件外部又如何呢?这就是本文论及的瘦控件。
瘦控件仅仅为用户提供一个GIS呈现和基本操作(放大缩小漫游选择)的地方,其他的操作,都放在控件外边的程序实现。
放在控件上的图元,只保留一个必备的ID列。
瘦控件有几个好处:
1 提高封装程度,便于GIS功能的重用和维护。
2 容易扩展控件原来的功能。例如下例《多行InfoTips的实现》,就是把tips的计算任务放在了控件外部;
3 可以采用更高效的纯数学的计算包来实现某些由Map控件实现的功能。例如笔者使用纯数学的方法来实现图元覆盖区域
的计算,速度提高何止十倍。
瘦控件要多瘦才算好?哪些基本功能必须实现? 外部如何实现控件原有的功能?如何扩展控件功能?如何保证控件性能?
这些问题都会影响到瘦控件的表现。下面笔者给出几个源代码片断,结合本人的另一个帖子http://excel.cnblogs.com/archive/2005/11/15/276694.html,
相信很容易就能制作出满足各位需求的足够瘦而且彪悍的MapXtreme控件了。
1 显示多行InfoTips
把鼠标放在图元上点击一下,就能出现tips,但是这个tips的内容是系统生成的,并且只能显示一行,也不知道能不能编程修改它的显示方式,所以我就写了几行代码,来实现自定义的多行tips显示。
步骤:
1)在Winform中加入MapControl和一个TextBox
2)将TextBox的属性MultiLine设为True, Visable设为False,BorderStyle设为FixSingle
3)捕获MapControl1的MouseDown和MouseUp事件,函数内容如下:
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private void mapControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cnblogs.com/Images/dot.gif)
{
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//如果没有转载任何tab文件,则返回
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if(mapControl1.Map.Layers.Count == 0 || this.currentLayerName=="")//currentLayerName是顶层Layer的名字,同时也是Table的名字
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return;
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
MapInfo.Engine.Selection selection=MapInfo.Engine.Session.Current.Selections.DefaultSelection;
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
MapInfo.Data.Table table=MapInfo.Engine.Session.Current.Catalog.GetTable(currentLayerName);
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
MapInfo.Data.IResultSetFeatureCollectionfeatureCollection=selection;
为软件组装的基本单位。所以在Winform的GIS开发中,如果仅仅把MapXtreme控件放进窗体,然后在这个窗体上添加所有
GIS的操作的代码,那么很快就会发现这个应用程序变得腐朽(corrupt)而不可维护。软件的坏味道(bad smell)来自封装程度
不足。
胖控件,就是指把大部分的计算工作都交给Map控件来完成,例如专题图的划分范围颜色配置,图元的距离,最短路径等;
MapXtreme实现这些功能也许很直接,却未必是最高效的。把计算放在控件外部又如何呢?这就是本文论及的瘦控件。
瘦控件仅仅为用户提供一个GIS呈现和基本操作(放大缩小漫游选择)的地方,其他的操作,都放在控件外边的程序实现。
放在控件上的图元,只保留一个必备的ID列。
瘦控件有几个好处:
1 提高封装程度,便于GIS功能的重用和维护。
2 容易扩展控件原来的功能。例如下例《多行InfoTips的实现》,就是把tips的计算任务放在了控件外部;
3 可以采用更高效的纯数学的计算包来实现某些由Map控件实现的功能。例如笔者使用纯数学的方法来实现图元覆盖区域
的计算,速度提高何止十倍。
瘦控件要多瘦才算好?哪些基本功能必须实现? 外部如何实现控件原有的功能?如何扩展控件功能?如何保证控件性能?
这些问题都会影响到瘦控件的表现。下面笔者给出几个源代码片断,结合本人的另一个帖子http://excel.cnblogs.com/archive/2005/11/15/276694.html,
相信很容易就能制作出满足各位需求的足够瘦而且彪悍的MapXtreme控件了。
1 显示多行InfoTips
把鼠标放在图元上点击一下,就能出现tips,但是这个tips的内容是系统生成的,并且只能显示一行,也不知道能不能编程修改它的显示方式,所以我就写了几行代码,来实现自定义的多行tips显示。
步骤:
1)在Winform中加入MapControl和一个TextBox
2)将TextBox的属性MultiLine设为True, Visable设为False,BorderStyle设为FixSingle
3)捕获MapControl1的MouseDown和MouseUp事件,函数内容如下:
![](http://www.cnblogs.com/Images/OutliningIndicators/None.gif)
private void mapControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
![](http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.cnblogs.com/Images/dot.gif)
{
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//如果没有转载任何tab文件,则返回
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if(mapControl1.Map.Layers.Count == 0 || this.currentLayerName=="")//currentLayerName是顶层Layer的名字,同时也是Table的名字
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return;
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
MapInfo.Engine.Selection selection=MapInfo.Engine.Session.Current.Selections.DefaultSelection;
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
MapInfo.Data.Table table=MapInfo.Engine.Session.Current.Catalog.GetTable(currentLayerName);
![](http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
MapInfo.Data.IResultSetFeatureCollectionfeatureCollection=selection