Итак, я наконец понимаю, что вы хотите, чтобы он закрывался только тогда, когда пользователь нажимает за его пределами. В этом случае событие Leave
должно работать просто отлично ... По какой-то причине у меня сложилось впечатление, что вы хотели, чтобы оно закрывалось всякий раз, когда они перемещали мышь за пределы вашего пользовательского раскрывающегося списка. Событие Leave
возникает всякий раз, когда ваш элемент управления теряет фокус, и если пользователь нажимает на что-то другое, он, безусловно, теряет фокус, поскольку объект, на который он нажал, получает фокус.
В документации также говорится, что это событие распространяется по цепочке управления вверх и вниз по мере необходимости:
События Enter
и Leave
являются иерархическими и будут каскадно перемещаться вверх и вниз по родительской цепочке, пока не будет достигнут соответствующий контроль. Например, предположим, что у вас есть форма с двумя элементами управления GroupBox, а каждый элемент управления GroupBox имеет один элемент управления TextBox. Когда курсор переносится из одного TextBox в другой, событие Leave
вызывается для TextBox и GroupBox, а событие Enter
вызывается для других GroupBox и TextBox.
Переопределение метода 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();
}
А затем для целей тестирования я создал форму, которая показывает выпадающий UserControl по команде:
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 не закрывается. Хм, а почему бы и нет? Ну, потому что сама форма не хочет фокусироваться. Только элементы управления могут получить фокус, и мы не нажали на элемент управления. И поскольку ничто другое не привлекло внимание, событие Leave
никогда не вызывалось, а это означает, что UserControl не знал, что должен был закрыться.
Если вам нужно, чтобы UserControl закрывался сам, когда пользователь нажимает на пустую область в форме, для этого вам потребуется специальная обработка. Поскольку вы говорите, что вас беспокоят только клики , вы можете просто обработать событие 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);
}
}
Да, эта последняя часть выглядит как хак. Лучшее решение, как уже упоминали другие, состоит в том, чтобы использовать функцию SetCapture
, чтобы дать указание Windows захватывать мышь над окном вашего UserControl. Свойство Capture
элемента управления предоставляет еще более простой способ сделать то же самое.