WPF: раскрытие списка сочетаний подчеркивает текст

Когда я печатаю в поле со списком, я автоматически открывает раскрывающийся список

searchComboBox.IsDropDownOpen = true;

Здесь проблема: текст выделяется, а следующий ключ переписывает предыдущий текст.

Как отключить выделение текста, когда открывается ComboBox DropDown?

Ответ 1

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

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

public override void OnApplyTemplate()
{
  base.OnApplyTemplate();

  var element = GetTemplateChild("PART_EditableTextBox");
  if (element != null)
  {
    var textBox = (TextBox)element;
    textBox.SelectionChanged += OnDropSelectionChanged;
  }
}

private void OnDropSelectionChanged(object sender, RoutedEventArgs e)
{
    // Your code
}

Затем в обработчике событий вы можете снова установить выбор, как хотите. В моем случае я вызывал IsDropDownOpen в коде. Сохраненный выбор, затем верните его в обработчик событий. Уродливо, но сделал трюк.

Ответ 2

У меня была такая же проблема, и, как некоторые из пользователей, являющихся новыми для WPF, изо всех сил пытались найти решение, данное Эйнаром Густштинссоном для работы. Поэтому в поддержку его ответа я прикладываю здесь шаги, чтобы заставить это работать. (Или более точно, как я получил это, чтобы работать).

Сначала создайте собственный класс combobox, который наследуется от класса Combobox. См. Код ниже для полной реализации. Вы можете изменить код в OnDropSelectionChanged в соответствии с вашими индивидуальными требованиями.

пространство имен MyCustomComboBoxApp {   используя System.Windows.Controls;

public class MyCustomComboBox : ComboBox
{
    private int caretPosition;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var element = GetTemplateChild("PART_EditableTextBox");
        if (element != null)
        {
            var textBox = (TextBox)element;
            textBox.SelectionChanged += OnDropSelectionChanged;
        }
    }

    private void OnDropSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
    {
        TextBox txt = (TextBox)sender;

        if (base.IsDropDownOpen && txt.SelectionLength > 0)
        {
            txt.CaretIndex = caretPosition;
        }
        if (txt.SelectionLength == 0 && txt.CaretIndex != 0)
        {
            caretPosition = txt.CaretIndex;
        }
    }

}

Убедитесь, что этот пользовательский класс комбо существует в одном проекте. THEN вы можете использовать приведенный ниже код, чтобы ссылаться на эту комбо в пользовательском интерфейсе.

<Window x:Class="MyCustomComboBoxApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:cc="clr-namespace:MyCustomComboBoxApp"
    Title="MainWindow" Height="350" Width="525" FocusManager.FocusedElement="{Binding ElementName=cb}">
<Grid>
    <StackPanel Orientation="Vertical">
        <cc:MyCustomComboBox x:Name="cb" IsEditable="True" Height="20" Margin="10" IsTextSearchEnabled="False" KeyUp="cb_KeyUp">
            <ComboBoxItem>Toyota</ComboBoxItem>
            <ComboBoxItem>Honda</ComboBoxItem>
            <ComboBoxItem>Suzuki</ComboBoxItem>
            <ComboBoxItem>Vauxhall</ComboBoxItem>
        </cc:MyCustomComboBox>
    </StackPanel>
</Grid>
</Window>

Вот оно! Любые вопросы, пожалуйста, спросите! Я сделаю все возможное, чтобы помочь.

Чрезвычайно важно для Эйнара Густштинсона за его решение!

Ответ 3

Я думаю, что в решении, предоставленном Эндрю N, есть что-то не так, как когда я это пробовал, событие Selection Changed TextBox помещало каретку в неправильное место. Поэтому я сделал это изменение, чтобы решить это.

namespace MyCustomComboBoxApp { using System.Windows.Controls;

public class MyCustomComboBox : ComboBox
{
    private int caretPosition;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var element = GetTemplateChild("PART_EditableTextBox");
        if (element != null)
        {
            var textBox = (TextBox)element;
            textBox.SelectionChanged += OnDropSelectionChanged;
        }
    }

    private void OnDropSelectionChanged(object sender, System.Windows.RoutedEventArgs e)
    {
        TextBox txt = (TextBox)sender;

        if (base.IsDropDownOpen && txt.SelectionLength > 0)
        {
            caretPosition = txt.SelectionLength; // caretPosition must be set to TextBox SelectionLength
            txt.CaretIndex = caretPosition;
        }
        if (txt.SelectionLength == 0 && txt.CaretIndex != 0)
        {
            caretPosition = txt.CaretIndex;
        }
    }
}

Ответ 4

В дополнение к ответу clsturgeon, я решил проблему, установив выделение при возникновении события DropDownOpened:

private void ItemCBox_DropDownOpened(object sender, EventArgs e)
{
    TextBox textBox = (TextBox)((ComboBox)sender).Template.FindName("PART_EditableTextBox", (ComboBox)sender);
    textBox.SelectionStart = ((ComboBox)sender).Text.Length;
    textBox.SelectionLength = 0;
}

Ответ 5

Когда comboxbox получает фокус, вы можете отключить выделение текста (т.е. не выделяя текст при событии GotFocus). Однако, когда вы выпадаете на поле со списком, система собирается найти элемент в списке и сделать выбранный элемент. Это, в свою очередь, автоматически выделяет текст. Если я понимаю поведение, которое вы ищете, я не считаю, что это возможно.