.NET WinForms ComboBox, идентичные объекты и событие SelectedIndexChanged

Странно, если честно. Код выглядит хорошо и должен был работать. Для отладки, не могли бы вы попробовать распечатать консоль заголовков объектов и поделиться тем, что вы там видите?

Кроме того, сделайте снимок ниже:

headers: new HttpHeaders({
  'username':  'Test',
  'password': 'Test123'
})
5
задан Keithius 9 December 2008 в 22:04
поделиться

4 ответа

Платформа.NET на самом деле не отслеживает выбранный индекс выпадающего списка поля комбинированного списка; это обрабатывается внутренне Windows API. В результате этого.NET уверена в Windows API для уведомления его, когда выбранный индекс изменяется посредством уведомления, отправленного в дескриптор окна поля комбинированного списка, так, чтобы это могло в свою очередь запустить событие SelectedIndexChanged.

К сожалению, оказывается, что конкретное уведомление, за которым наблюдает.NET (CBN_SELCHANGE быть точным), НЕ покрывает все возможные сценарии, в которых мог измениться выбранный индекс. А именно, CBN_SELCHANGE только отправляется Windows API, если пользователь нажимает или выбирает использование клавиш со стрелками, объекта в выпадающем списке. Однако в поле комбинированного списка стиля DropDown, действие открытия поля комбинированного списка заставляет Windows смотреть на текст в части редактирования поля комбинированного списка, перерывать список объектов для соответствия, и если соответствие найдено, автоматически выберите объект соответствия (или первый объект соответствия, если существует несколько объектов соответствия). Это может изменить выбранный индекс, но НЕ отправляет a CBN_SELCHANGE уведомление, таким образом.NET пропускает то, что это изменило и не запускает событие SelectedIndexChanged.

Windows делает все это в поле комбинированного списка стиля DropDown, потому что пользователь не должен выбирать что-то в выпадающем списке; они могут ввести то, что они хотят. Так каждый раз, когда Вы открываете поле комбинированного списка, оно предполагает, что пользователь, возможно, изменил текст и попытки повторно синхронизировать с тем, что находится в списке, если оно может.

В Вашем случае при открытии поля комбинированного списка во второй раз оно повторно синхронизирует и выбирает первое соответствие для текста в части редактирования, которая является "John Doe" № 0 и изменение выбранного индекса к 0 без.NET, являющейся знающим.

Таким образом, это в основном - ошибка в Платформе.NET. К сожалению, нет никакого идеального обходного решения - Вы не можете заставить Windows не делать пересинхронизацию, и нет никакого события, которое стреляет прямо после того, как пересинхронизация происходит, в котором можно получить новый выбранный индекс. (Событие DropDown на самом деле стреляет прямо, прежде чем пересинхронизация происходит, таким образом, это не будет видеть нового индекса.) О лучшем можно сделать, обработать событие DropDownClosed, предположить, что индекс, возможно, изменился в той точке и действует соответственно.

17
ответ дан 18 December 2019 в 07:57
поделиться

Ответ Eric был очень полон, но я был удивлен видеть, что он не закончился "..., но действительно, необходимо спросить себя, почему Вы заполняете поле комбинированного списка с дублирующимися объектами". Ошибке платформы .NET несомненно позволили существовать, потому что при использовании управления, как предназначено, чтобы позволить пользователю выбирать объект из списка, Вы не сталкиваетесь с этой ошибкой.

Как пользователь собирается дифференцироваться между идентичными записями? Почему они предпочли бы один другому? Существует ли другое значение к различным объектам? Если так, затем наличие дублирующихся записей неоднозначно, который всегда является плохим дизайном удобства использования. В противном случае затем у Вас не должно быть дублирующихся объектов.

Единственный сценарий, о котором я могу думать, где это могло бы иметь смысл, - когда у Вас есть большой список, состоящий из нескольких групп связанных объектов, где один или несколько объектов логически вписываются больше чем в одну группу, таким образом, Вы хотите отобразить его в обоих разделах.

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

2
ответ дан 18 December 2019 в 07:57
поделиться

Бывают случаи, когда наличие повторяющихся элементов в списке не только допустимо, но и желательно. Рассмотрим поле со списком OpenFileDialog, которое вы видите в Visual Studio, когда нажимаете кнопку «Открыть файл». Появится поле со списком с такими элементами, как «Мой компьютер», «Рабочий стол», «Мои документы» и т. Д. Для имен папок в списке отображается только краткое имя. Полный путь не отображается. И поэтому вполне возможно, что папка имеет то же (короткое) имя, что и один из ее потомков.

Итак, представьте следующую структуру папок:

C:\
C:\A
C:\A\B
C:\A\B\A

Совершенно допустимая структура. В моей реализации я установил для свойства DataSource значение BindingList объектов. ValueMember объекта - это полное имя файла, а DisplayMember - это короткое имя файла. В поле со списком должно отображаться:

C:\
    A
        B
            A

Идеально хороший дизайн пользовательского интерфейса. Отступ предполагает вложение папок.

Но когда я устанавливаю для поля со списком SelectedValue значение «C: \ A \ B \ A», выбирается не тот элемент. Элемент, который следует выбрать, является последним (4-м элементом) в списке, но вместо этого выбирается 2-й элемент (индекс 1). И установка SelectedIndex = 3 не работает должным образом. Опять же, выбирается второй элемент, а не последний.

Похоже, что здесь происходит то, что при установке SelectedValue или SelectedIndex значение преобразуется с использованием свойства DisplayMember, и элемент управления выполняет поиск от начала до конца для соответствие. Он должен выполнять поиск с использованием свойства ValueMember. Пример кода ниже. Приветствую, если кто-нибудь может подтвердить, что это ошибка или что-то, что я сделал неправильно.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace ComboBoxTest
{
   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         if (DesignMode)
            return;

         BindingList<CBItem> items = new BindingList<CBItem>();
         items.Add(new CBItem("A", @"C:\A"));
         items.Add(new CBItem("B", @"C:\A\B"));
         items.Add(new CBItem("A", @"C:\A\B\A"));

         comboBox.DisplayMember = "DisplayValue";
         comboBox.ValueMember = "RealValue";
         comboBox.DataSource = items;

         comboBox.SelectedValue = @"C:\A\B\A";
      }
   }

   class CBItem
   {
      public CBItem(string displayValue, string realValue)
      {
         _displayValue = displayValue;
         _realValue = realValue;
      }

      private readonly string _displayValue, _realValue;

      public string DisplayValue { get { return _displayValue; } }
      public string RealValue { get { return _realValue; } }
   }
}
1
ответ дан 18 December 2019 в 07:57
поделиться

Аналогичная проблема возникает при отсутствии идентичных элементов, если вы вводите произвольный текст, который соответствует не в точности, а первым символам. Если пользователь не открывает раскрывающийся список, повторная синхронизация не происходит, и выбранный индекс равен -1, как и ожидалось. (Пользователь намеревается не выбирать один из элементов) Теперь пользователь закрывает диалог и открывает его снова. Вы, как программист, восстанавливаете поле со списком с текстом, введенным пользователем, и этот текст автоматически заполняется до частичного совпадения элемента без запуска события. Если пользователь закрывает диалоговое окно, текст изменяется без уведомления. Эта проблема не возникает, если текст не соответствует ни одному элементу.

0
ответ дан 18 December 2019 в 07:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: