如何在运行时创建MapContro并绑定到TocControl

12 篇文章 0 订阅
12 篇文章 3 订阅

做了一个MDI程序,想在代码中动态创建地图控件,代码如下:

        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.Location = new System.Drawing.Point(0, 0);
            axMapControl.Size = new System.Drawing.Size(100, 100);
            axMapControl.Dock = DockStyle.Fill;
            axMapControl.Name = "mapControl";
            this.axTOCControl1.SetBuddyControl(axMapControl);
            panel.Location = new System.Drawing.Point(0, 0);
            panel.Size = new System.Drawing.Size(100, 100);
            panel.Dock = DockStyle.Fill;
            panel.Controls.Add(axMapControl);
            e.Control = panel;
        }

代码每次执行到SetBuddyControl都会报错,错误信息如下:

错误信息是:“The supplied buddy is not a supported object”,查看SetBuddyControl的说明,里面说他的参数可以使一下任何一种:MapControl, PageLayoutControl, SceneControl, GlobeControl or object implementing ITOCBuddy,而我们赋给的正是一个MapControl,这是没有问题的。检查发现,上述代码在执行到SetBuddyControl时,axMapControl对象是无法转换为ITOCBuddy接口对象的。这里很蹊跷,因为当我们把一个地图控件拖入窗体时,该控件也是按照上述方式创建的,为何到了这里就不行呢?因此对比窗体自动生成地图控件的代码,发现里面是这样写的:

            this.axMapControl1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.axMapControl1.Location = new System.Drawing.Point(0, 0);
            this.axMapControl1.Name = "axMapControl1";
            this.axMapControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axMapControl1.OcxState")));
            this.axMapControl1.Size = new System.Drawing.Size(247, 185);
            this.axMapControl1.TabIndex = 0;

逐一排查,发现最可疑的地方就是OcxState,搜索了相关信息,得到的答案是OcxState存储的是控件的状态信息,既然我们的代码没有这一行,那我们就加上试一下,于是我拿另个绘制在窗体上的地图控件的OcxState赋给它,代码如下:

        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.Location = new System.Drawing.Point(0, 0);
            axMapControl.Size = new System.Drawing.Size(100, 100);
            axMapControl.Dock = DockStyle.Fill;
            axMapControl.Name = "mapControl";
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
            axMapControl.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axLicenseControl1.OcxState")));
            this.axTOCControl1.SetBuddyControl(axMapControl);
            panel.Location = new System.Drawing.Point(0, 0);
            panel.Size = new System.Drawing.Size(100, 100);
            panel.Dock = DockStyle.Fill;
            panel.Controls.Add(axMapControl);
            e.Control = panel;
        }

实验发现,问题依旧,这表明这个问题和OcxState没有什么关系。继续研究,经过仔细对比,发现在InitializeComponent中,还有两行,那就是所有控件都需要调用的BeginInit和EndInit方法,那么问题是不是跟这个有关呢?于是做如下实验:

        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,这样就出现了上面的异常。



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深蓝静音

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值