vba读取第三方软件窗体数据_vba读取第三方软件窗体数据

vba读取第三方软件窗体数据_vba读取第三方软件窗体数据(原创内容,elig首发于博客园,转载请注明出处)今天在修改一个以前的项目时发现如下问题:IDE环境:VS2010privatevoidfrmAdd_Load(objectsender,EventArgse){Init

vba读取第三方软件窗体数据_vba读取第三方软件窗体数据"

(原创内容,elig首发于博客园,转载请注明出处)

今天在修改一个以前的项目时发现如下问题:

IDE环境 : VS2010


private

void
frmAdd_Load(
object
sender, EventArgs e)
{

InitializeComboBox();

}


private

void
InitializeComboBox()
{

cboCategory.DropDownStyle

=
ComboBoxStyle.DropDownList;
cboCategory.DataSource

=
mainForm.CategoryList;
cboCategory.DisplayMember

=


CategoryName

;
cboCategory.ValueMember

=


CategoryID

;
cboSencondaryCategory.DropDownStyle

=
ComboBoxStyle.DropDownList;
cboSencondaryCategory.DataSource

=
mainForm.SecondaryList;
cboSencondaryCategory.DisplayMember

=


SecondaryCategoryName

;
cboSencondaryCategory.ValueMember

=


SecondaryCategoryID

;
        //(原创内容,elig首发于博客园,转载请注明出处)

/*
如果没有传进来对应的数据,则按初始值(-1)显示
*/

cboCategory.SelectedIndex

=

1
; //为了方便阅读,这里改为常量显示
cboSencondaryCategory.SelectedIndex

=

1
; //为了方便阅读,这里改为常量显示

}


private

void
cboCategory_SelectedValueChanged(
object
sender, EventArgs e)
{


if
(cboCategory.SelectedIndex
==


1
)
{

cboSencondaryCategory.DataSource

=
mainForm.SecondaryList;
cboSencondaryCategory.DisplayMember

=


SecondaryCategoryName

;
cboSencondaryCategory.ValueMember

=


SecondaryCategoryID

;
}

else

{

cboSencondaryCategory.DataSource

=
secondaryCategoryBLL.SelectByCategoryID((
int
)cboCategory.SelectedValue);
cboSencondaryCategory.DisplayMember

=


SecondaryCategoryName

;
cboSencondaryCategory.ValueMember

=


SecondaryCategoryID

;
}

}

在这种情况下,(int)cboCategory.SelectedValue部分,无论如何得不到正确的结果,一直显示转换出错。照理是不应该有这样的问题的。

经过研究发现,一模一样的代码(cboCategory_SelectedValueChanged()内的内容),在SelectedIndexChanged事件中也一样无法正确获得所需要的结果。

但是,在SelectionChangeCommitted()中则可以正常工作.

(原创内容,elig首发于博客园,转载请注明出处)

于是,我对此做了几个测试.过程如下:

首先,测试几个模块里分别添加如下几行:


int
id
=
Convert.ToInt32(cboCategory.SelectedValue);
MessageBox.Show(id.ToString());

1.在cboCategory_SelectedIndexChanged()   cboCategory_SelectedValueChanged()中添加,编译无法通过,报错如下:

   无法将类型为“myProject.Model.Category”的对象强制转换为类型“System.IConvertible”。

2.在普通方法或者load事件里,添加,则可以正常通过。

(原创内容,elig首发于博客园,转载请注明出处)

然后,测试代码改为如下:


Category id
=
(Category)(cboCategory.SelectedValue);

if
(id
==

null
)
{

MessageBox.Show(


Test

);
}

1.在普通方法里调用,第一行可以正确编译通过,id == null 条件成立

2.在load事件,以及SelectionChangeCommitted,SelectedIndexChanged,SelectedValueChanged事件里,都报错如下:

   无法将类型为“System.Int32”的对象强制转换为类型“myProject.Model.Category”。

最后,测试如下代码:


MessageBox.Show(cboCategory.SelectedIndex.GetType().ToString());
String str

=
cboCategory.SelectedValue.ToString();
MessageBox.Show(str);

int
id
=
Convert.ToInt32(str);
MessageBox.Show(id.ToString());

1.load事件  普通方法 以及   SelectionChangeCommitted事件 都可以得到预期结果。

    type : System.Int32

2.而SelectionChangeCommitted,SelectedIndexChanged事件里

    type : System.Int32

    str = myProject.Model.Category

    转int后出错

(原创内容,elig首发于博客园,转载请注明出处)

虽然当时没有想明白问题到底出在哪里,但是解决方法就是上面提到的,把需要实现的代码写到SelectionChangeCommitted事件里,就可以正常地得到预期的结果。

项目结束后花了点时间仔细研究了下这个问题,因为同样的代码放在不同的地方却会出现如此丰富多彩的结果,实在让人忍不住。

最后发现,我们如果在SelectedIndexChanged,SelectedValueChanged两者任意一个事件里,把测试代码加到如下if判断里:


if
(cboCategory.SelectedIndex
>=

1
)


//
测试代码


那么3个事件都能正常编译通过。

注意:问题就出在这个红色的1上,在SelectedIndexChanged,SelectedValueChanged里,只能判断到index >= 1

有人就要问了,comboBox的index不是从0开始的吗?

非常正确!

但是只要把条件改为 >= 0 那么窗体加载时必定报错。

我们来看看这3个事件的区别:

SelectedIndexChanged,SelectedValueChanged是在任何情况下,只要改变了它们监视的值(index或者valueMember)就会触发对应事件

而我们都知道,在控件生成的时候,这2个值不可避免地要发生改变。也就是说,每次改变都会触发这个事件。

而SelectionChangeCommitted事件,官方的翻译解释是:当从下拉列表中选择项而下拉列表关闭时发生。

但是实际是这个翻译是不准确的,因为我装的不是英文的VS环境,所以无从知晓原文如何,但是实际上,该事件个人理解,更准确的翻译是,用户对该控件的选择项作出任何改变时发生。

这个“任何”包括:鼠标点击,获得焦点的情况下方向键上下选择。

(原创内容,elig首发于博客园,转载请注明出处)

在我的问题中,SelectedIndexChanged,SelectedValueChanged无法正确运作,是因为同样的代码在这两个事件中,无法对index = 0的item做处理,或者说SelectedValue的值不明确。从index = 1开始,SelectedValue的(int)转换非常正常。但是正因为这两个事件连系统对comboBox控件作出的改动都会监视,所以不可避免的会在生成第一行的时候即触发事件,导致接触到不正常的index = 0的行。

(原创内容,elig首发于博客园,转载请注明出处)

这个问题应该是一个BUG,如果有朋友知道问题具体出在哪个地方,非常欢迎指出。

关于解决方案实际上,至少在目前看来,非极端的情况下,都可以用SelectionChangeCommitted事件取代SelectedIndexChanged,SelectedValueChanged。而且如果需要写的代码比较复杂,又没有必要在窗体加载生成comboBox的items集合的时候即触发对应事件,那么没有必要用SelectedIndexChanged,SelectedValueChanged,至少,在加载过程中所触发的事件,属于浪费系统资源的行为。

补充内容:根据@admin的提示,终于把之前的所有问题想通了:

  问题如下:其实现在发现,这不是一个BUG。出问题的机制在于:在执行

 

cboCategory.DataSource = mainForm.CategoryList;

之后,执行下一步之前,因为根据DataSource开始生成comboBox的item生成的时候,就已经触发了SelectedIndexChanged,SelectedValueChanged事件。在这个时候,因为还没有执行到下面的手动指定ValueMember命令。那么,这个时候comboBox的ValueMember则默认为Model.Category类型。

而comboBox有个特点,在生成下拉项之前,它的index是-1,因为尚未有任何项(可以新建一个空白的comboBox然后观察它的SelectedIndex)。在生成之后,先是SelectedIndex会等于0,这也是 我们通常看到的如果在生成之后不指定它的index,则默认是选中第一项的。然后再生成更多的项的时候,被选中的项是不会变的,依然保持第一个。

这就是为什么如果和DisplayMember一起指定了ValueMember的时候,如果if条件里控制了index >= 1的时候才执行相应代码,就不会出错。因为这个时候已经执行完后面的内容了。在

cboCategory.DataSource = mainForm.CategoryList;所产生的动作中,SelectedIndex始终保持着非-1即0的状态。在这个时候始终不会执行SelectedIndexChanged,SelectedValueChanged事件

所以后面的就迎刃而解了

(原创内容,elig首发于博客园,转载请注明出处)

转载于:https://www.cnblogs.com/elig/archive/2011/02/12/1951756.html

今天的文章vba读取第三方软件窗体数据_vba读取第三方软件窗体数据分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/77103.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注