В выпадающем списке выберите элемент только мышью или клавишей Enter - PullRequest
3 голосов
/ 11 октября 2011

У меня есть WPF ComboBox
Мне нужно изменить поведение по умолчанию в всплывающем списке.

Теперь нажатием клавиш up и down SelectedItem автоматически изменится.
Мне нужно изменить SelectedItem только нажатием клавиши Enter или щелчком мыши.

Как это можно сделать?

Я вложил в подкласс ComboBox:

protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
    Debug.Write("Pressed " + e.Key+ " ");
    if (e.Key == System.Windows.Input.Key.Up || e.Key == System.Windows.Input.Key.Down)
    {
        // ???
        e.Handled = true;
        return;
    }
    base.OnPreviewKeyDown(e);
}

Этот код не работает - всплывающее окно не отображается, и пользователь не может выбирать элементы. Что я должен написать и где? :)

Спасибо.

UPD1:

Мне нужна та же функциональность, что и ComboBox's, открыто всплывающее окно, и пользователь может выбирать элементы мышью.
Каждый элемент может быть перемещен мышью, но не выбран. Выбор делается только нажатием кнопки мыши. Мне нужно то же самое. «Вверх» и «Вниз» только подсвечивает элементы во всплывающем окне, но SelectedItem будет изменено только нажатием Enter или щелчком мыши.

UPD2: Если я нажимаю кнопку мыши, открывающую всплывающее окно в ComboCox, я могу выделить элементы в всплывающем окне мышью, но SelectedItem изменится, только если я нажму на элемент.

Мне нужна та же функциональность с помощью клавиатуры. Если я начну печатать в ComboBox, откроется Popup. И я должен выделять элементы с помощью клавиатуры Up и Down. TextBox в ComboBox не должен изменяться во время выделения, а SelectedItem должен изменяться только при нажатии Enter (или щелчке мыши)

UPD3: Ссылка на демонстрационное решение: скачать

Ответы [ 5 ]

2 голосов
/ 11 октября 2011

Код, который у вас, кажется, работает нормально, просто добавьте проверку, чтобы убедиться, что DropDown открыт перед отменой ключевого события

protected override void OnPreviewKeyDown(KeyEventArgs e)
{
    Debug.Write("Pressed " + e.Key + " ");
    if (!base.IsDropDownOpen && (e.Key == Key.Up || e.Key == Key.Down))
    {
        e.Handled = true;
        return;
    }
    base.OnPreviewKeyDown(e);
}
2 голосов
/ 11 октября 2011

Вы должны обработать это событие на всех ComboBoxItem s в выпадающем списке.

   <ComboBox.Resources>
        <Style TargetType="{x:Type ComboBoxItem}">
           <EventSetter Event="PreviewKeyDown" Handler="OnPreviewKeyDown" />
        </Style> 
  </ComboBox.Resources>

РЕДАКТИРОВАТЬ:

В коде позади вы можете добавитьследующий код в конструкторе MyComboBox после InitializeComponent() сделать это ...

  var comboBoxItemstyle = new Style(typeof (ComboBoxItem));  
  comboBoxItemstyle.Setters.Add(
        new EventSetter(PreviewKeyDownEvent,
                new KeyEventHandler(OnPreviewKeyDown)));
  this.Resources.Add(typeof (ComboBoxItem), comboBoxItemstyle);

Надеюсь, это поможет.

0 голосов
/ 04 апреля 2019

Лучше использовать ComboBox. OnDropDownClosed (EventArgs) Метод

https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.combobox.ondropdownclosed?view=netframework-4.7.2#System_Windows_Forms_ComboBox_OnDropDownClosed_System_EventArgs_

PS: для элементов управления Infracistics (UltraComboEditor) это событие OnAfterCloseUp.

0 голосов
/ 08 мая 2015

Вот решение, которое у меня сработало -

public class CustomComboBox : ComboBox
{
    private int _currentItemIndex;
    private string _rowColor = "#E7E7E7";
    private string _selectedRowColor = "#FFFFC6";        

    protected override void OnDropDownOpened(EventArgs e)
    {
        _currentItemIndex = base.SelectedIndex;
        base.OnDropDownOpened(e);
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (base.IsDropDownOpen)
        {
            if (e.Key == Key.Up || e.Key == Key.Down)
            {
                ComboBoxItem currentItem;
                var colorConverter = new BrushConverter();

                if (_currentItemIndex > -1 && _currentItemIndex != base.SelectedIndex)
                {
                    currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
                    currentItem.Background = (Brush)colorConverter.ConvertFromString(_rowColor);
                }

                if (e.Key == Key.Up)
                {
                    _currentItemIndex -= 1;
                    if (_currentItemIndex < 0)
                    {
                        _currentItemIndex = 0;
                    }
                }
                else if (e.Key == Key.Down)
                {
                    _currentItemIndex += 1;
                    if (_currentItemIndex > base.Items.Count - 1)
                    {
                        _currentItemIndex = base.Items.Count - 1;
                    }
                }

                currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
                currentItem.Background = (Brush)colorConverter.ConvertFromString(_selectedRowColor);
                currentItem.BringIntoView();

                e.Handled = true;
                return;
            }
            else if (e.Key == Key.Enter)
            {
                base.SelectedItem = base.Items[_currentItemIndex];
            }
        }
        base.OnPreviewKeyDown(e);
    }

    protected override void OnDropDownClosed(EventArgs e)
    {
        if (_currentItemIndex > -1 && base.Items[_currentItemIndex] != base.SelectedItem)
        {
            var colorConverter = new BrushConverter();
            ComboBoxItem currentItem = (ComboBoxItem)base.ItemContainerGenerator.ContainerFromIndex(_currentItemIndex);
            currentItem.Background = (Brush)colorConverter.ConvertFromString(_rowColor);
        }
        base.OnDropDownClosed(e);
    }
}
0 голосов
/ 19 января 2014

По моему мнению, вы должны создать свойство - IsKeyNavigation (например, IsMouseOver)

protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
    Debug.Write("Pressed " + e.Key+ " ");
    if (e.Key == System.Windows.Input.Key.Up || e.Key == System.Windows.Input.Key.Down)
    {
        VisualStateManager.GoToState(this, "KeyNavigation", true);
        e.Handled = true;
        return;
    }
    base.OnPreviewKeyDown(e);
}

И если нажата Key.Up или Key.Down, вы должны определить элемент навигации и изменить VisualState.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...