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]
[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.
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.
[Leido, Inspirado, copiado y traducido de este texto original]
Un ComboBox es un control compuesto de dos partes:
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.
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
© 1997 - - La Güeb de Joaquín | |||||
Joaquín Medina Serrano
|
|||||
|
Codificación | |
Fecha de creación | |
Última actualización | |
![]() |