C # ComboBox GotFocus - PullRequest
       23

C # ComboBox GotFocus

11 голосов
/ 12 октября 2009

У меня есть C # ComboBox с использованием WPF. У меня есть код, который выполняется при активации ComboBox GotFocus. Проблема в том, что событие GotFocus выполняется каждый раз, когда делается выбор из ComboBox. Например, GotFocus выполняется, когда вы сначала нажимаете на ComboBox, а затем, когда вы делаете выбор, даже если вы не нажимали ни на какой другой элемент управления.

Можно ли предотвратить запуск этого события, если в списке делается выборка, или в обработчике события есть флаг или что-то еще, что можно использовать для определения, был ли обработчик события GotFocus запущен как результат выбора пользователем элемента в списке?

Ответы [ 3 ]

13 голосов
/ 08 марта 2011

Эту проблему можно решить с помощью следующей проверки:

private void myComboBox_GotFocus(object sender, RoutedEventArgs e)
{
    if (e.OriginalSource.GetType() == typeof(ComboBoxItem))
        return;
    //Your code here
}

Этот код отфильтрует все события фокуса от предметов (поскольку они используют событие пузырьковой маршрутизации).Но есть еще одна проблема - специфическое поведение фокуса WPF ComboBox: когда вы открываете выпадающий список с элементами, ваш ComboBox теряет фокус и элементы получают.При выборе какого-либо предмета - предмет теряет фокус и 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;
    }
}

Выберите из этого примера то, что вам действительно нужно для вашего приложения.

0 голосов
/ 17 марта 2017

Другое решение используется для определения того, является ли новый сфокусированный элемент существующим элементом в выпадающем списке. Если true, то событие LostFocus не должно выполняться, потому что поле со списком все еще имеет фокус. В противном случае элемент вне поля со списком получил фокус.

В приведенном ниже фрагменте кода я добавил функциональность в пользовательский класс со списком

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... */
        }
    }
}
0 голосов
/ 12 октября 2009

Я не слишком горячий на WPF; но если вы пытаетесь обнаружить изменения в списке (нажмите на новое значение и т. д.), вы можете использовать события SelectedIndexChanged ..

С другой стороны, если вы действительно хотите просто знать, когда элемент управления сфокусирован, вы можете отфильтровать его, сказав что-то вроде:

if (combo1.Focused && combo1.SelectedIndex == -1)
{
     ...
}

..? Это действительно зависит от того, что вы пытаетесь обнаружить, точно.

...