当应用程序失去焦点时,Windows 窗体组合框会触发 SelectionChangeCommitted、SelectedValueChanged 和 SelectedIndexChanged 事件

Posted

技术标签:

【中文标题】当应用程序失去焦点时,Windows 窗体组合框会触发 SelectionChangeCommitted、SelectedValueChanged 和 SelectedIndexChanged 事件【英文标题】:Windows Form ComboBox fires SelectionChangeCommitted, SelectedValueChanged and SelectedIndexChanged event when application loses focus 【发布时间】:2011-04-01 13:44:04 【问题描述】:

我有包含组合框的 .Net 2.0 Windows 表单。我编写了以下代码来填充组合框,然后将其绑定到 Int 类型的 ProductType 属性。

// Populate Combo

cmbProduct.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
cmbProduct.DataSource = new DataView(productDataSet.Tables[0]);
cmbProduct.DisplayMember = displayColumnName_;
cmbProduct.ValueMember = idColumnaName_;

// Add Databindings

cmbProduct.DataBindings.Add("SelectedValue", this, "ProductType").DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;

问题

    运行应用程序。 单击组合框的下拉箭头,但不要选择任何项目。 按任意键(例如 ALT+TAB、Windows 键等)将焦点从当前 Windows 窗体应用程序转移。

这会引发异常和应用程序崩溃。以下是从输出窗口获取的详细信息。

发生“System.ArgumentException”类型的第一次机会异常 在 System.Windows.Forms.dll 类型“System.DBNull”的对象中不能 转换为类型“System.Int32”。在 System.ComponentModel.ReflectPropertyDescriptor.SetValue(对象 组件,对象值) 在 System.Windows.Forms.BindToObject.SetValue(对象值) 在 System.Windows.Forms.Binding.PullData(布尔重新格式化,布尔力) 在 System.Windows.Forms.Binding.Target_PropertyChanged(对象发送者,EventArgs e) 在 System.EventHandler.Invoke(对象发送者,EventArgs e) 在 System.Windows.Forms.ListControl.OnSelectedValueChanged(EventArgs e) 在 System.Windows.Forms.ComboBox.OnSelectedValueChanged(EventArgs e) 在 System.Windows.Forms.ComboBox.OnSelectedIndexChanged(EventArgs e) 在 System.Windows.Forms.ComboBox.WmReflectCommand(消息和 m) 在 System.Windows.Forms.ComboBox.WndProc(消息和 m) 在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息& m) 在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息和 m) 在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam) 在 System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) 在 System.Windows.Forms.Control.SendMessage(Int32 消息,IntPtr wparam,IntPtr lparam) 在 System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd,消息& m) 在 System.Windows.Forms.Control.WmCommand(消息和 m) 在 System.Windows.Forms.Control.WndProc(消息和 m) 在 System.Windows.Forms.ScrollableControl.WndProc(消息和 m) 在 System.Windows.Forms.ContainerControl.WndProc(消息和 m) 在 System.Windows.Forms.Form.WndProc(消息和 m) 在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息& m) 在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息和 m) 在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam) 在 System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) 在 System.Windows.Forms.NativeWindow.DefWndProc(消息和 m) 在 System.Windows.Forms.Control.DefWndProc(消息和 m) 在 System.Windows.Forms.Control.WmCommand(消息和 m) 在 System.Windows.Forms.Control.WndProc(消息和 m) 在 System.Windows.Forms.ComboBox.WndProc(消息和 m) 在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息& m) 在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息和 m) 在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam) 在 System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG 和 msg,HandleRef hwnd,Int32 msgMin,Int32 msgMax,Int32 删除) 在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 原因, Int32 pvLoopData) 在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 原因,ApplicationContext 上下文) 在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 原因,ApplicationContext 上下文) 在 System.Windows.Forms.Application.Run(Form mainForm)

我在事件处理程序中添加了一些调试语句来检查事件顺序。 输出窗口详情如下:

cmbProduct_SelectionChangeCommitted occured - SelectedValue is NULL
cmbProduct_SelectedValueChanged occured - New SelectedValue is NULL
The thread 0x1728 has exited with code 0 (0x0).
cmbProduct_SelectedIndexChanged occured - New SelectedIndex is -1
The thread 0x1250 has exited with code 0 (0x0).

问题

为什么当应用程序失去焦点且组合框状态为 OPEN 时,.Net 会触发 SelectionChangeCommittedSelectedValueChangedSelectedIndexChanged 事件?

【问题讨论】:

【参考方案1】:

代码看起来很完美。该问题可能是由于 .net 框架中的错误。有专家能证实吗?

避免异常的一种解决方法是 - 如果 SelectedValue 为 NULL,则存储“ProductType”属性的默认值。

例如,如果 ProductType 的默认值为 -1,则

cmbProduct.DataBindings["SelectedValue"].DataSourceNullValue = -1; 

希望,这会有所帮助!

罗宾

【讨论】:

【参考方案2】:

听起来您问错了问题:“为什么组合会导致焦点丢失?”而不是“为什么抛出异常?”

罗宾正确回答了重要的问题。

用户无需执行您提供的复杂的 3 个步骤即可查看异常 - 只需选择有问题的 (null) 索引即可。

【讨论】:

以上是关于当应用程序失去焦点时,Windows 窗体组合框会触发 SelectionChangeCommitted、SelectedValueChanged 和 SelectedIndexChanged 事件的主要内容,如果未能解决你的问题,请参考以下文章

C++ Builder中如何让窗体一直显示最前,焦点不失去,就是点不了别的窗体,切换不了窗体,总处在被激活状态

PyQt5:当列表失去焦点时设置 QListWidget 选择颜色

窗体在调用其子窗体的 Hide 方法后失去焦点

如何让WPF中窗体失去焦点后TextBox中的被选中文本仍然保持高亮状态?

javascript脚本事件,窗体失去焦点事件怎么写,怎么触发事件????

WPF 处理textbox的样式问题,点击获得焦点背景颜色变化,当点击窗体其他地方(非控件),textbox自动