С# ComboBox GotFocus
У меня есть С# ComboBox
с использованием WPF. У меня есть код, который выполняется при активации ComboBox
GotFocus
. Проблема в том, что событие GotFocus
выполняется каждый раз, когда выделение производится из ComboBox
. Например, GotFocus
выполняется при первом нажатии на ComboBox
, а затем, когда вы делаете выделение, даже если вы не нажимаете на какой-либо другой элемент управления.
Возможно ли предотвратить запуск этого события, если в списке сделан выбор или есть флаг или что-то еще в обработчике событий, которое может быть использовано для определения того, был ли обработчик события GotFocus
уволен как результат выбора пользователем элемента в списке?
Ответы
Ответ 1
Вы можете решить эту проблему при следующей проверке:
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(ComboBoxItem))
return;
//Your code here
}
Этот код будет фильтровать все фокусные события из элементов (поскольку они используют событие маршрутизации пузырьков). Но есть еще одна проблема - специфическое поведение фокуса WPF ComboBox: когда вы открываете раскрывающийся список с элементами, которые теряют фокус и элементы, получаемые ComboBox. Когда вы выбираете элемент item item, теряющий фокус, и ComboBox возвращается. Выпадающий список похож на другой элемент управления. Вы можете увидеть это простым кодом:
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
Trace.WriteLine("Got " + DateTime.Now);
}
}
private void myComboBox_LostFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
Trace.WriteLine("Lost " + DateTime.Now);
}
}
Итак, вы получите в любом случае два фокусных события: когда вы выбираете ComboBox и когда вы выбираете что-то в нем (фокус вернется в ComboBox).
Чтобы отфильтровать возвращенный фокус после выбора элемента, вы можете попытаться использовать события DropDownOpened
/DropDownClosed
с некоторым флагом поля.
Итак, последний код с одним событием фокуса:
private bool returnedFocus = false;
private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem) && !returnedFocus)
{
//Your code.
}
}
private void myComboBox_LostFocus(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() != typeof(ComboBoxItem))
{
ComboBox cb = (ComboBox)sender;
returnedFocus = cb.IsDropDownOpen;
}
}
Выберите из этих примеров то, что вам действительно нужно для вашего приложения.
Ответ 2
Я не слишком горячий в WPF; но если вы пытаетесь обнаружить изменения в списке (нажмите новое значение и т.д.), вы можете использовать события SelectedIndexChanged.
С другой стороны, если вы действительно хотите знать просто, когда элемент управления сосредоточен, вы можете отфильтровать его, сказав что-то вроде:
if (combo1.Focused && combo1.SelectedIndex == -1)
{
...
}
..? Это действительно зависит от того, что вы пытаетесь обнаружить, точно.
Ответ 3
Другое решение - определить, является ли новый сфокусированный элемент существующим элементом в поле со списком. Если true, то событие LostFocus не должно выполняться, потому что в поле со списком все еще есть фокус. В противном случае элемент вне поля со списком получал фокус.
В нижеприведенном snipplet кода я добавил функциональность в пользовательский класс combobox
public class MyComboBox : System.Windows.Controls.Combobox
{
protected override void OnLostFocus(RoutedEventArgs e)
{
//Get the new focused element and in case this is not an existing item of the current combobox then perform a lost focus command.
//Otherwise the drop down items have been opened and is still focused on the current combobox
var focusedElement = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this));
if (!(focusedElement is ComboBoxItem && ItemsControl.ItemsControlFromItemContainer(focusedElement as ComboBoxItem) == this))
{
base.OnLostFocus(e);
/* Your code here... */
}
}
}