2010-06-02 114 views
70

C#, .NET 4.0, VS2010.El evento ComboBox- SelectionChanged tiene un valor anterior, no es un valor nuevo

Nuevo en WPF. Tengo un ComboBox en mi MainWindow. Enganché el evento SelectionChanged de dicho cuadro combinado. Sin embargo, si examino el valor del cuadro combinado en el controlador de eventos, tiene el valor anterior. Esto suena más como un evento "SelectionChanging" que como un evento SelectionChanged.

¿Cómo obtengo el nuevo valor del ComboBox después de que la selección haya sucedido realmente?

Actualmente:

this.MyComboBox.SelectionChanged += new SelectionChangedEventHandler(OnMyComboBoxChanged); 

... 
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    string text = this.MyComboBox.Text; 
} 

Nota, me sale el mismo comportamiento si uso el objeto que se está aprobada en los argumentos de eventos, por ejemplo, e.OriginalSource.

+2

Acabo de tropezar con el mismo problema - ¡gracias! ¿Es eso realmente un error, y debería haber sido nombrado * 'SelectionChanging' * en primer lugar? – Jan

Respuesta

83

Según MSDN, e.AddedItems:

obtiene una lista que contiene los elementos que se han seleccionado.

lo que podría utilizar:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    string text = (e.AddedItems[0] as ComboBoxItem).Content as string; 
} 

También es posible usar SelectedItem si utiliza string valores para el Items del sender:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    string text = (sender as ComboBox).SelectedItem as string; 
} 

o

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    string text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string; 
} 

Dado que tanto Content y SelectedItem son objetos, un enfoque más seguro sería utilizar .ToString() en lugar de as string

+10

interesante ... tiene el nuevo valor. Y RemovedItems tiene el viejo. Ese nombre de evento es un poco inapropiado, al menos en mi humilde opinión. Cuando veo SelectionChanged, espero que el estado del objeto, bueno, haya cambiado. Sin embargo, puedo ver cómo esto nos da un poco más de información. – Matt

+0

Sí, creo que es porque el cambio se ha producido, ¿pero no se ha comprometido? Eso es solo una suposición. Es posible que pueda obtener el texto del elemento seleccionado, vea mi edición. – SwDevMan81

+0

Ambos funcionan, ¡gracias! – Matt

1

La segunda opción no funcionó para mí porque el elemento .Texto estaba fuera de alcance (C# 4.0 VS2008). Este fue mi solución ...

string test = null; 
foreach (ComboBoxItem item in e.AddedItems) 
{ 
    test = item.Content.ToString(); 
    break; 
} 
9

Esto funcionó para mí:

private void AppName_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    ComboBoxItem cbi = (ComboBoxItem)AppName.SelectedItem; 
    string selectedText = cbi.Content.ToString(); 
} 
+0

de alguna manera solo SelectedItem se llena con el nuevo elemento, no SelectedValue. – mauris

0

que necesitaba para resolver esto en VB.NET. Esto es lo que tengo que parece funcionar:

Private Sub ComboBox1_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles ComboBox_AllSites.SelectionChanged 
    Dim cr As System.Windows.Controls.ComboBoxItem = ComboBox1.SelectedValue 
    Dim currentText = cr.Content 
    MessageBox.Show(currentText) 
End Sub 
0
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString(); 
} 
+3

No proporcione respuestas de solo código. Por favor, brinde una explicación de por qué su solución es la respuesta. –

40

Uso caso DropDownClosed en lugar de SelectionChanged si desea que el valor actual del cuadro combinado.

private void comboBox_DropDownClosed(object sender, EventArgs e) 
{ 
    MessageBox.Show(comboBox.Text) 
} 

Es así de simple.

+0

Gracias amigo, funcionó como un encanto. –

+10

@jvelez Creo que no se disparará cuando se usa un teclado. – NoviceProgrammer

+0

que apesta. ¡NoviceProgrammer que sabía ...! – hidden

-2

Esto debería funcionar para usted ...

int myInt= ((data)(((object[])(e.AddedItems))[0])).kid; 
+1

¿Puedes explicarnos cómo responde esto a la pregunta? –

0

Es raro que SelectedItem contiene los datos frescos, mientras que SelectedValue no lo hace. Me parece un error.Si sus artículos en el cuadro combinado son objetos que no sean ComboBoxItems, se necesita algo como esto: (mi ComboBox contiene KeyValuePair s)

var selectedItem = (KeyValuePair<string, string>?)(sender as ComboBox).SelectedItem; 
if (!selectedItem.HasValue) 
    return; 

string selectedValue = selectedItem.Value.Value; // first .Value gets ref to KVPair 

ComboBox.SelectedItem puede ser nulo, mientras que Visual Studio me sigue diciendo que no puede KeyValuePair ser nulo. Es por eso que lancé el SelectedItem a un nullable KeyValuePair<string, string>?. Luego compruebo si selectedItem tiene un valor distinto de null. Este enfoque debería ser aplicable al tipo de elemento seleccionado.

-3

Lo resolví usando el evento DropDownClosed porque esto se dispara un poco después de que se cambia el valor.

0

Si realmente necesita el evento SelectionChanged, entonces la mejor respuesta es la respuesta de SwDevMan81. Sin embargo, si está comenzando con WPF, entonces puede querer aprender cómo hacer las cosas de la manera WPF, que es diferente a los viejos días de Windows Forms que solían confiar en eventos como SelectionChanged, con WPF y el patrón View View Model de Model View, debería usar enlaces. Aquí está un ejemplo de código:

// In the Views folder: /Views/MyWindow.xaml: 
// ... 
<ComboBox ItemsSource="{Binding MyViewModel.MyProperties, RelativeSource={RelativeSource AncestorType=Window}}" 
     SelectedItem="{Binding MyViewModel.MyProperty , RelativeSource={RelativeSource AncestorType=Window}}" /> 
// ... 



// In the Views folder: /Views/MyWindow.xaml.cs: 
public partial class MyWindow : Window 
{ 
    public MyViewModelClass MyViewModel { 
     get { return _viewModel; } 
     private set { _viewModel = value;} 
    } 

    public MyWindow() 
    { 
     MyViewModel.PropertyChanged += MyViewModel_PropertyChanged; 

    } 

    void MyViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "MyProperty") 
     { 
      // Do Work 
      // Put your logic here! 
     } 
    } 
} 

using System.ComponentModel; 

// In your ViewModel folder: /ViewModels/MyViewModelClass.cs: 
public class MyViewModelClass : INotifyPropertyChanged 
{ 
    // INotifyPropertyChanged implementation: 
    private void NotifyPropertyChanged(string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } 
    public event PropertyChangedEventHandler PropertyChanged; 

    // Selected option: 
    private string _myProperty; 
    public string MyProperty { 
     get { return _myProperty; } 
     set { _myProperty = value; NotifyPropertyChanged("MyProperty"); } 
    } 

    // Available options: 
    private List<string> _myProperties; 
    public List<string> MyProperties { 
     get { return _myProperties; } 
     set { _myProperties = value; NotifyPropertyChanged("MyProperties"); } 
    } 

} 
32

El valor correcto para comprobar aquí es el propiedad SelectedItem .

A ComboBox es un control compuesto con dos de sus partes son:

  1. La Parte texto: el valor en el esta parte corresponde a la texto propiedad del ComboBox.
  2. Pieza Selector (es decir, la parte "desplegable"): El elemento seleccionado en esta parte corresponde a la propiedad SelectedItem.

Expanded ComboBox Parts

La imagen de arriba fue tomada inmediatamente después de la ComboBox se amplió (es decir, antes de seleccionar un nuevo valor). En este punto, ambos Texto y SelectedItem son "Información", suponiendo que los elementos del ComboBox fueran cadenas. Si los elementos de ComboBox fueran todos los valores de un Enum llamado "LogLevel", SelectedItem sería actualmente LogLevel.Info.

Cuando un elemento de la lista desplegable que se hace clic en, el valor de SelectedItem se cambia y la SelectionChanged evento se produce. El texto propiedad no se actualiza, sin embargo, sin embargo, como la parte texto no se actualiza hasta después de la SelectionChanged controlador está terminada.Esto se puede observar por poner un punto de interrupción en el controlador y mirando el control:

ComboBox at breakpoint in SelectionChanged handler

ya que la parte texto no se ha actualizado en este punto, el texto propiedad devuelve el seleccionado anteriormente valor.

+1

Completó la expansión y ayudó a realizar mi enlace en la propiedad Text en lugar del SelectedItem correcto. – cmousset

4

Esto funcionó para mí:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;    
} 
+0

Esto es muy importante. La respuesta aceptada no muestra explícitamente que 'sender' contiene el' SelectedItem' correcto. – Jess

0
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    int NewProjID = (e.AddedItems[0] as kProject).ProjectID; 
    this.MyProject = new kProject(NewProjID); 
    LoadWorkPhase(); 
} 

El uso de la e.AddedItems[0] as kProject donde kProject es una clase que contiene los datos trabajaron para mí, ya que no cumplía con los RemovedItems [0] antes de que yo he hecho esta distinción explícita. Gracias SwDevMan81 por la información inicial que respondió esta pregunta por mí.

1

El siguiente evento se activa por cualquier cambio de texto en el ComboBox (cuando se cambia el índice seleccionado y cuando el texto se modifica editando también).

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" /> 
Cuestiones relacionadas