如何在运行时创建MapContro并绑定到TocControl
做了一个MDI程序,想在代码中动态创建地图控件,代码如下:
错误信息是:“The supplied buddy is not a supported object”,查看SetBuddyControl的说明,里面说他的参数可以使一下任何一种:MapControl, PageLayoutControl, SceneControl, GlobeControl or object implementing ITOCBuddy,而我们赋给的正是一个MapControl,这是没有问题的。检查发现,上述代码在执行到SetBuddyControl时,axMapControl对象是无法转换为ITOCBuddy接口对象的。这里很蹊跷,因为当我们把一个地图控件拖入窗体时,该控件也是按照上述方式创建的,为何到了这里就不行呢?因此对比窗体自动生成地图控件的代码,发现里面是这样写的:
private void tabbedView1_QueryControl(object sender, DevExpress.XtraBars.Docking2010.Views.QueryControlEventArgs e) { Panel panel = new Panel(); ESRI.ArcGIS.Controls.AxMapControl axMapControl = new ESRI.ArcGIS.Controls.AxMapControl(); axMapControl.BeginInit(); axMapControl.Location = new System.Drawing.Point(0, 0); axMapControl.Size = new System.Drawing.Size(100, 100); axMapControl.Dock = DockStyle.Fill; axMapControl.Name = "mapControl"; panel.Location = new System.Drawing.Point(0, 0); panel.Size = new System.Drawing.Size(100, 100); panel.Dock = DockStyle.Fill; panel.Controls.Add(axMapControl); axMapControl.EndInit(); this.axTOCControl1.SetBuddyControl(axMapControl); e.Control = panel; }
很幸运,问题就解决了。搜索了一下BeginInit和EndInit,在MSDN中的说法是,这两个方法是ISupportInitialize接口中方法,ISupportInitialize接口用于实现对对象进行批量初始化处理时的通知事务。调用BeginInit通知对象批量初始化开始,调用EndInit告诉对象批量初始化结束。使用这个接口的意义在于:对象内部某些属性可能具有相互依赖性,因此一些具有依赖性的处理需要在初始化完成之后才能进行。而ISupportInitialize正是为了实现这个功能而生,它的BeginInit方法的作用就是告诉对象当前正在初始化,从而不要去执行那些需要在初始化完成之后才能进行的操作。这里,我们使用ArcGIS engine的MapControl也存在这个问题,在AxMapControl没有调用EndInit之前,其内部的一些属性是拒绝访问的,因此当我们把new出来的这个AxMapControl对象作为伙伴对象赋给TocControl的时候,该对象认为初始化还没有结束,从而拒绝访问或者返回null,这样就出现了上面的异常。