所以我终于明白,你只希望它在用户点击时关闭它。在这种情况下,Leave event 应该可以正常工作...出于某种原因,我的印象是,每当他们将鼠标移到自定义下拉列表之外时,您都希望它关闭。每当您的控件失去焦点时,就会引发Leave 事件,如果用户单击其他内容,它肯定会失去焦点,因为他们单击的内容获得焦点。
文档还说,此事件根据需要在控制链上下级联:
Enter 和Leave 事件是分层的,将在父链上下级联,直到达到适当的控制。例如,假设您有一个带有两个 GroupBox 控件的 Form,并且每个 GroupBox 控件都有一个 TextBox 控件。当插入符号从一个 TextBox 移动到另一个时,会为 TextBox 和 GroupBox 引发 Leave 事件,并为另一个 GroupBox 和 TextBox 引发 Enter 事件。
覆盖您的 UserControl 的 OnLeave 方法是处理此问题的最佳方法:
protected override void OnLeave(EventArgs e)
{
// Call the base class
base.OnLeave(e);
// When this control loses the focus, close it
this.Hide();
}
然后出于测试目的,我创建了一个表单,在命令中显示下拉用户控件:
public partial class Form1 : Form
{
private UserControl1 customDropDown;
public Form1()
{
InitializeComponent();
// Create the user control
customDropDown = new UserControl1();
// Add it to the form's Controls collection
Controls.Add(customDropDown);
customDropDown.Hide();
}
private void button1_Click(object sender, EventArgs e)
{
// Display the user control
customDropDown.Show();
customDropDown.BringToFront(); // display in front of other controls
customDropDown.Select(); // make sure it gets the focus
}
}
一切都与上面的代码完美配合,除了有一件事:如果用户点击表单的空白区域,UserControl 不会关闭。嗯,为什么不呢?好吧,因为表单本身不需要焦点。只有 controls 可以获得焦点,我们没有点击一个控件。而且因为没有其他东西偷走了焦点,Leave 事件从未被引发,这意味着 UserControl 不知道它应该自行关闭。
如果您需要 UserControl 在用户单击表单中的空白区域时自行关闭,则需要对此进行一些特殊情况处理。既然你说你只关心clicks,你可以只处理表单的Click 事件,并将焦点设置到不同的控件:
protected override void OnClick(EventArgs e)
{
// Call the base class
base.OnClick(e);
// See if our custom drop-down is visible
if (customDropDown.Visible)
{
// Set the focus to a different control on the form,
// which will force the drop-down to close
this.SelectNextControl(customDropDown, true, true, true, true);
}
}
是的,这最后一部分感觉就像一个 hack。正如其他人所提到的,更好的解决方案是使用SetCapture function 来指示Windows 将鼠标捕获到您的UserControl 窗口上。控件的Capture property 提供了一种更简单的方法来做同样的事情。