Wpf - ComboBox.SelectionChanged

Descripción general

Explicación de porqué en un control Wpf - ComboBox., no coincide el valor de la [propiedad Text], con el valor seleccionado [Porpiedad SelectedItem] cuando las leemos desde un controlador del evento [SelectionChanged]

[TOC] Tabla de Contenidos


↑↑↑

Introducción

[Propiedad ComboBox.Text] Obtiene o establece el texto asociado al control. Es decir, el valor visible en el ComboBox.

[Propiedad ComboBox.SelectedItem] Obtiene o establece el elemento seleccionado actualmente en el elemento ComboBox.

[Evento Selector.SelectionChanged] Se produce cuando cambia la selección de un control que contiene un Selector.


↑↑↑

¿Cuál es el problema?

Pues que al interceptar un evento [SelectionChanged], y obtener el valor del ComboBox con la propiedad [Text], se obtiene el valor seleccionado viejo, no el que acabamos de seleccionar.

Una observación importante: Este problema ocurre cuando usamos el escuchador de eventos. Si usamos un Binding de la propiedad [Text] con otro control, este problema no aparece y todo funciona correctamente.


↑↑↑

¿Por qué ocurre esto?

[Leido, Inspirado, copiado y traducido de este texto original]

Un ComboBox es un control compuesto de dos partes:

Antes de seleccionar un elemento

La imagen de anterior está tomada inmediatamente después de que el ComboBox se expandiera, justo después de mostrar el menú desplegable, y antes de seleccionar un nuevo valor. En este punto [Text] y [SelectedItem] tienen el mismo valor.

Por ejemplo, tomando los valores que aparecen en la imagen, y por simplificar, suponiendo que los elementos del ComboBox sean cadenas. El valor de [Text] = Info, y el valor de [SelectedItem] = Info

Cuando se presiona un elemento en el menú desplegable, se cambia el valor de [SelectedItem] y provoca el evento [SelectionChanged]. Pero la propiedad [Text] no se actualiza todavía, sino que el control espera para actualizarla a que acabe el evento [SelectionChanged], por esa razón, si dentro del código del evento llamamos a la propiedad [Text], obtendremos el valor "antiguo" de esta propiedad. Este comportamiento, puede observarse colocando un punto de interrupción en el controlador y mirando el control

Puesto que la Parte del texto no ha sido actualizado en este punto, la propiedad Text devuelve el valor seleccionado previamente.

Despues de seleccionar un elemento

↑↑↑

la solución

En resumen. Si queremos obtener el valor nuevo, seleccionado en el ComboBox dentro de un evento [SelectionChanged]. Tendremos que usar el valor [SelectedItem] en lugar de [Text].

Un ejemplo

Private Sub uc_OrdenarFotosDos_SelectionChanged(
            sender As Object, e As SelectionChangedEventArgs)
        ' Obtener el ComboBox que dispara el evento
        ' en realidad no es necesario, se puede usar directamente 
        ' el combo llamándolo por su [x: Name]
        Dim ojbComboBox As ComboBox = CType(sender, ComboBox)
        ' de esta forma obtendré el valor anterior (viejo)  del ComboBox
        'Me.textBoxResultado.Text = Me.uc_OrdenarFotosDos.Text
        ' Obtener el valor de la propiedad SelectedItem.
        Dim value As String = CType(ojbComboBox.SelectedItem, String)
        ' mostrarla, (por ejemplo) en un textBox :-)
        Me.textBoxResultado.Text = value
End Sub



Otro ejemplo del año 2021 ejemplo

    ''' <summary>
    ''' El nivel de dificultad del sudoku.
    ''' Debe estar entre 1 [Facilísimo] y 7 [Extremadamente difícil] (ambos incluidos)
    ''' </summary>
    ''' <value>
    '''    [1 = Facilísimo] y  [7 = Extremadamente difícil]
    ''' </value>
    ''' <remarks>
    '''     <para>   -----------------------------                      </para>
    '''     <para>     [1 = muy fácil]                                   </para>
    '''     <para>     [7 = muy difícil]                                </para>
    '''     <para>     [valores de 4 o 5 para una dificultad aceptable] </para>
    '''     <para>   -----------------------------                      </para>
    '''     <para>        Nivel                         Posiciones      </para>
    '''     <para>        dificultad                    visibles        </para>
    '''     <para>        1 - Facilísimo             -    36-40         </para>
    '''     <para>        2 - Muy fácil              -    31-35         </para>
    '''     <para>        3 - Fácil                  -    28-30         </para>
    '''     <para>        4 - Normal                 -    25-27         </para>
    '''     <para>        5 - Difícil                -    22-24         </para>
    '''     <para>        6 - Muy difícil            -    20-21         </para>
    '''     <para>        7 - Extremadamente difícil -    19-17         </para>
    '''     <para>   Observación menos de 17 se puede resolver pero los sudokus no son únicos</para>
    ''' </remarks>
    Public Property NivelDeDificultad As Integer = 4
    '
    '
    '
    ''' <summary>
    '''   El evento [SelectionChanged]  del combo que se dispara cuando se cambia
    ''' </summary>
    Private Sub ComboBoxNiveles_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
        '--------------------------------------------------
        ' Evitar errores cuando se esta iniciando la ventana
        If Me.TextBoxInformes Is Nothing Then
            Exit Sub
        End If
        If sender Is Nothing Then
            Exit Sub
        End If
        '--------------------------------------------------
        ' Obtener el ComboBox que dispara el evento
        ' en realidad no es necesario, se puede usar directamente
        ' el combo llamándolo por su [x: Name]
        Dim ojbComboBox As ComboBox = CType(sender, ComboBox)
        '--------------------------------------------------
        ' OJO, de esta otra forma obtendré el valor anterior (viejo)  del ComboBox
        ' Me.textBoxResultado.Text = Me.uc_OrdenarFotosDos.Text
        '--------------------------------------------------
        ' Obtener el valor de la propiedad SelectedItem.
        ' que es un objeto [ComboBoxItem]
        If ojbComboBox.SelectedItem Is Nothing Then
            Exit Sub
        End If
        Dim objCombo As ComboBoxItem = ojbComboBox.SelectedItem
        '--------------------------------------------------
        ' Variables de trabajo local
        ' La cadena completa que contiene el combo box          | Ejemplo ["0 - Selecciona un nivel"]
        Dim cadenaCompletaComboItem As String
        ' El numero del nivel que esta a principio de la cadena | Ejemplo ["0"]
        Dim numeroNivel As String
        ' El texto que describe la cadena que tiene el nivel    | Ejemplo ["Selecciona un nivel"]
        Dim textoNivel As String
        '--------------------------------------------------
        ' Para evitar errores cuando se esta iniciando la ventana
        If objCombo.Content Is Nothing Then
            ' Si el combo es NULL pongo un valor por defecto
            cadenaCompletaComboItem = "0 - Selecciona un nivel"
        Else
            ' En caso contrario extraigo su valor [Content]
            ' y lo trasformo en una cadena
            cadenaCompletaComboItem = CType(objCombo.Content, String)
        End If
        '--------------------------------------------------
        ' Extraigo las subcadenas
        numeroNivel = cadenaCompletaComboItem.Substring(0, 1)
        textoNivel = cadenaCompletaComboItem.Substring(4)
        ' Convertir el nivel, en un numero y guardarla en la propiedad [NivelDeDificultad
        NivelDeDificultad = Integer.Parse(numeroNivel)
        '
        ' Mostrarla, (por ejemplo) en un textBox :-)
        'Me.TextBoxInformes.Text = String.Format(
        '    "Nivel de dificultad elegido [{0}] - [{1}]",
        '    numeroNivel,
        '    textoNivel)
        '-----------------------------
        ' Refactorizado a una cadena interpolada
        Me.TextBoxInformes.Text = $"Nivel de dificultad elegido [{numeroNivel }] - [{textoNivel }]"
        '--------------------------------------------------
        ' Marcar el evento como tratado
        e.Handled = True
    End Sub

↑↑↑

A.2.Enlaces

[Para saber mas]
Wpf – Cargar en un ListBox una enumeración del sistema
Wpf – Cargar en un ListBox/ComboBox una enumeración creada por nosotros
Wpf – Cargar una colección en una enumeración
Wpf – Extender un control ComboBox que cargue una enumeración
[Grupo de documentos]
[Documento Index]
[Documento Start]
[Imprimir el Documento]
© 1997 - - La Güeb de Joaquín
Joaquín Medina Serrano
Ésta página es española

Codificación
Fecha de creación
Última actualización
[HTML5 Desarrollado usando CSS3]