Часть Editbox для ComboBox автоматически выбирается

У меня есть небольшая проблема, которая раздражает меня в течение нескольких часов.

В моем приложении WinForms (.NET 3.5) я создаю несколько ComboBoxes (DropDownStyle = DropDown) в TableLayoutPanel во время выполнения и заполняю его строками. ComboBoxes настроены на автоматическое изменение размера (Anchor = Left | Right).

Проблема заключается в том, что всякий раз, когда ComboBoxes изменяются в размерах (то есть диалоговом окне изменяется), часть editbox ComboBox получает выделение/выделение целиком. По-моему, это создает очень запутывающий эффект для клиента, которого я хочу избежать.

Проблема не возникает, если ComboBox имеет фиксированный размер.

Также обратите внимание, что изменение DropDownStyle не является вариантом - мне нужна возможность ввода текста вручную.

Я уже пытался испортить процесс переопределения метода OnPaint, который не совсем сработал. Я также попытался очистить выбор в событии ComboBox.Resize, который работал в некотором роде, но выглядел как очень уродливое решение - было много мерцания, намеренно выбранный текст стал снят с выбора, и мне пришлось бы добавить обработчик событий к каждому и каждый ComboBox в моем диалоговом окне.

Есть ли лучшее решение этой проблемы?

Спасибо заранее.

С уважением, Andy

Ответы

Ответ 1

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

    foreach (var cb in Controls.OfType<ComboBox>())
    {
        cb.Resize += (sender, e) => {
            if (!cb.Focused)
                cb.SelectionLength = 0;
        };
    }

намеренно выбранный текст снят с выбора

Эта ошибка WinForms не влияет на выбранные ComboBoxes, поэтому, игнорируя тех, у кого есть Focus, мы позаботимся о проблеме потери текущих выборов.

Мне нужно добавить обработчик событий для каждого ComboBox на моем диалоговое окно.

Взятый уход за петлей foreach. Поместите его в InitializeComponent() или ваш .ctor, если вы не хотите сломать конструктор, или попросите дизайнера сломать это.

было много мерцания

Я вижу только мерцание, если я изменяю размер очень быстро, но я нахожусь на Win7, чтобы он мог быть другим в XP.

Ответ 2

Ого. Спасибо, ребята!

По-видимому, эта ошибка сохранилась много лет. Я создаю UserControl с .Net 4 (Visual Studio 2010). Вот моя небольшая измененная версия кода bsneeze.

Приветствия

using System.Windows.Forms;
using System.Linq;

public MyUserControlCtor()
{
    InitializeComponent();

    foreach( Control ctrl in Controls)
    {
        ComboBox cb = ctrl as ComboBox;
        if (cb != null)
        {
            cb.Resize += (sender, e) =>
            {
                if (!cb.Focused)
                    this.FCHZ_ComboBox.SelectionLength = 0;
            };
        }
    } 
}

Ответ 3

Ни один из ответов до сих пор не работал у меня. Единственный надежный метод, который я нашел, заключается в том, чтобы асинхронно публиковать сообщение через BeginInvoke, который устанавливает SelectionLength обратно в ноль после завершения всех остальных действий над элементом управления. Количество мерцаний очень раздражает и непрофессионально, но это лучшее, что я мог бы придумать... до сих пор.

internal class FixedComboBox : ComboBox
{
    protected override void OnResize(EventArgs e)
    {
        if (IsHandleCreated && !Focused)
        {
            BeginInvoke((Action)(() =>
                {
                    SelectionLength = 0;
                }));
        }
        base.OnResize(e);
    }
}

Ответ 4

Это, по-видимому, ошибка в собственной реализации Windows ComboBox с DropDownStyle of DropDown.

Исправление, подробно описанное в других ответах здесь (установка свойства SelectionLength в 0 (ноль) в событии ComboBox Resize), работает большую часть времени.

Однако я обнаружил, что даже это исправление для работы с этой ошибкой не всегда работает. Если ComboBox находится в TableLayoutPanel, а если TableLayoutPanel имеет более одного столбца с типом Percent размера, то это исправление часто не работает.

Картинка стоит тысячи слов. См. Следующий снимок экрана формы, которую я сделал, чтобы продемонстрировать проблему.

введите описание изображения здесь

Ответ 5

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

Я действительно добился этого в VB.Net, но он должен применить то же самое к С#.

Ответ 6

Обработать событие Resize для родительского контейнера ComboBox. Поместите эту строку туда:

MyComboBox.SelectionLength = 0

Пример (VB, очевидно):

Private Sub MyControl_Resize(sender As Object, e As EventArgs) Handles Me.Resize

    MyComboBox.SelectionLength = 0

End Sub

Удачи вам!

- BP

Ответ 7

Я работал, чтобы изменить selectionLength на 0, когда вызывается WM_WINDOWPOSCHANGED. Работает даже с параметром tableLayoutPanel, установленным на%.

protected override void WndProc(ref Message m) {
    base.WndProc(ref m);

    if(m.Msg == 0x0047) {   // WM_WINDOWPOSCHANGED = 0x0047 
        if (SelectionLength != 0) {
            SelectionLength = 0;
        }
    }
}