Как я могу заполнить поле со списком, когда запускается событие GotFocus?

#c# #.net #wpf #vb.net #xaml

Вопрос:

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

Нажмите на выпадающий список :

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

Попробуйте выбрать первый пункт :

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

Вот мой код :

 Private Sub agence_GotFocus(sender As Object, e As RoutedEventArgs) Handles agence.GotFocus
    strsql = "Select age_cpt, age_abrege   ' '   age_nom as age_abregenom from gen_agence where age_soc = " amp; societe.SelectedValue
    Dim da As New SqlDataAdapter(strsql, connSQLServer)
    Dim ds As New DataSet()
    da.Fill(ds, "t")
    agence.ItemsSource = ds.Tables("t").DefaultView
    agence.DisplayMemberPath = "age_abregenom"
    agence.SelectedValuePath = "age_cpt"
End Sub

 

Как я могу это сделать ?

Я не хочу использовать MVVM.

Комментарии:

1. «Я не хочу использовать MVVM». — почему? MVVM-это типичная реализация WPF. Многое гораздо сложнее реализовать вне этого шаблона.

2. Покажите код вашей текущей реализации (XAML и Sharp), соответствующий вашей проблеме.

3. @EldHasp я знаю, но мне нужно перенести приложение VBA в WPF VB.Net. Поэтому я хочу сохранить существующий код как можно больше.

4. @EldHasp Я обновил свой вопрос и добавил немного кода

5. Я не могу воспроизвести вашу проблему. Выполнено простейшее назначение источнику массива строк comboBox.ItemsSource ="First Second Third".Split(); . Установите точку останова после назначения таблицы (в строке agence.DisplayMemberPath = ... ) и проверьте содержимое этой таблицы. Может быть, он у вас пустой?

Ответ №1:

Проблема в том, что это событие срабатывает несколько раз.
Ниже я покажу демо-код в Sharpe (у меня нет VB.Сеть загружена в студию), но код прост, вы должны повторить его самостоятельно на BASIC без каких-либо проблем.

         private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(  eventCount);
            ComboBox comboBox = (ComboBox)sender;

            // Try the second option by excluding the following line
            if (comboBox.ItemsSource == null)
                comboBox.ItemsSource = "First,Second,Third".Split(',');
        }
 

Код должен проверять наличие null, чтобы не повторно подключать коллекцию.
Комментируя эту строку, вы воспроизведете свою проблему.
После запуска на выполнение и попытки выбрать элемент, вы увидите в окне «Вывод», что событие произошло несколько раз.

Похоже, что изменение списка в момент его расширения каким-то образом нарушает логику внутренних привязок выпадающего списка.

Есть несколько способов исправить это, но для этого нам нужно знать, почему вы выбрали эту инициализацию элемента — когда на нем сосредоточено внимание.

Несколько способов:

  1. Обнуление источника перед назначением новой коллекции.
         private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(  eventCount);
            ComboBox comboBox = (ComboBox)sender;

            comboBox.ItemsSource = null;
            comboBox.ItemsSource = "First,Second,Third".Split(',');
        }
 
  1. Установка коллекции один раз при загрузке выпадающего списка.
         <ComboBox Loaded="OnLoaded"/>
 
         private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(  eventCount);
            ComboBox comboBox = (ComboBox)sender;

            comboBox.ItemsSource = "First,Second,Third".Split(',');
        }
 

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

Ответ на дополнительный вопрос:

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

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

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

Способ, который вы выбрали для инициализации списка, очень необычен. Каждый раз, когда вы работаете в выпадающем списке, вы делаете запросы к базе данных три — четыре раза. Я никогда не встречал такой реализации и не понимаю ее смысла.

Объясните, зачем вам это нужно?

Комментарии:

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

Ответ №2:

Я нашел способ сделать то, что хотел : использовать DropDownOpened событие вместо GotFocus

 Private Sub agence_DropDownOpened(sender As Object, e As EventArgs) Handles agence.DropDownOpened
        '... Fill the ComboBox
End Sub
 

Заполните a ComboBox в GotFocus событии работает в VBA, но не в VB.Net.

В VB.Сеть, которую я не могу использовать GotFocus , потому что событие запускается несколько раз. Это срабатывает, когда :

  • Я открываю ComboBox
  • Я провожу мышкой по предметам
  • Я выбираю элемент

Более того, это может вызвать исключение stackoverflow.

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

Использование DropDownOpened события было лучшим вариантом в моем случае.

Спасибо людям, которые помогли мне найти решение.