Elie
Elie

Reputation: 142

How can I fill a ComboBox when GotFocus event is triggered?

I want to fill a ComboBox when the GotFocus event is triggered. I tried to fill my ComboBox in the GotFocus event, but it doesn't seem to work. Items are visible in the dropdown menu but when I want to select one of them the collection is cleared

Click on the ComboBox :

enter image description here

Try to select the first item :

enter image description here

Here is my code :

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 = " & 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

How can I manage that ?

I don't want to use MVVM.

Upvotes: 0

Views: 520

Answers (2)

Elie
Elie

Reputation: 142

I found a way to do what I wanted : Use the DropDownOpened event instead of GotFocus

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

Fill a ComboBox in the GotFocus event works in VBA but not in VB.Net.

In VB.Net I can't use GotFocus cause the event is triggered multiple time. It's triggered when :

  • I open the ComboBox
  • I pass my mouse over the items
  • I select an item

Moreover, this can trigger a stackoverflow exception.

I know it's better to fill a ComboBox before open it. I am in an application migration procedure and I cannot afford to change the entire code structure.

Use the DropDownOpened event was the best option in my case.

Thanks to the people who helped me find a solution.

Upvotes: 0

EldHasp
EldHasp

Reputation: 7918

The problem is that this event fires multiple times.
Below I will show a demo code in Sharpe (I do not have VB.Net loaded in the Studio), but the code is simple, you should repeat it yourself in BASIC without any problems.

        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(',');
        }

The code should check for null so as not to reconnect the collection.
Commenting out this line will reproduce your problem.
After launching for execution and trying to select an item, you will see in the "Output" window that the event has occurred several times.

It looks like changing the list at the moment of its expansion somehow breaks the logic of the internal bindings of the ComboBox.

There are several ways to fix this, but for this we need to know why you chose this initialization of the element - when the focus is on it.

Several ways:

  1. Nulling the source before assigning a new collection.
        private void OnGotFocus(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(++eventCount);
            ComboBox comboBox = (ComboBox)sender;

            comboBox.ItemsSource = null;
            comboBox.ItemsSource = "First,Second,Third".Split(',');
        }
  1. Setting the collection once when loading the ComboBox.
        <ComboBox Loaded="OnLoaded"/>
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine(++eventCount);
            ComboBox comboBox = (ComboBox)sender;

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

Other implementation options are possible, but I need to know more details about your task in order to choose how best to do it.

Answer to the additional question:

Nulling the source before assigning a new collection is a good idea. Now I can move my mouse over the values in the dropdown menu. However, when I select a value, the field is cleared.

If it is not a string array, then the selection can be cleared. When you enter the event, you recreate the tables each time. And the rows of these tables, although they are the same in content, will not be considered the same instance. You selected a row from one table, then you rewrote the source, and the new source does not have this row. The selection is reset.

I already wrote above that in order to choose the optimal solution, I need more details of your problem.

The way you have chosen to initialize the list is very unusual. Each time you work in the ComboBox, you make queries to the database three to four times. I have never met such a implementation and I do not understand its meaning.

Explain why do you need this?

Upvotes: 1

Related Questions