ComboBox- Acara SelectionChanged memiliki nilai lama, bukan nilai baru


91

C #, .NET 4.0, VS2010.

Baru di WPF. Saya memiliki ComboBox di MainWindow saya. Saya mengaitkan acara SelectionChanged dari kotak kombo tersebut. Namun, jika saya memeriksa nilai kotak kombo di event handler, itu memiliki nilai lama. Ini terdengar lebih seperti acara "SelectionChanging", daripada acara SelectionChanged.

Bagaimana saya mendapatkan nilai baru dari ComboBox setelah pemilihan benar-benar terjadi?

Saat ini:

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

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

Catatan, saya mendapatkan perilaku yang sama jika saya menggunakan objek yang diteruskan dalam acara args, egeOriginalSource.


2
Saya baru saja tersandung masalah yang sama - terima kasih! Apakah itu benar-benar bug, dan itu seharusnya dinamai SelectionChangingsejak awal?
Jan

Jawaban:


110

Menurut MSDN, e.AddedItems:

Mendapat daftar yang berisi item yang dipilih.

Jadi Anda bisa menggunakan:

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

Anda juga bisa menggunakan SelectedItemjika Anda menggunakan stringnilai untuk Itemsdari sender:

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

atau

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

Karena keduanya Contentdan SelectedItemmerupakan objek, pendekatan yang lebih aman akan digunakan .ToString()daripadaas string


11
menarik ... itu memiliki nilai baru. Dan RemovedItems memiliki yang lama. Nama acara itu agak keliru, setidaknya IMHO. Ketika saya melihat SelectionChanged, saya mengharapkan status objek, yah, telah berubah. Saya dapat melihat bagaimana ini memberi kita sedikit lebih banyak informasi.
Matt

1
Ya, saya pikir itu karena perubahan telah terjadi, tetapi belum dilakukan? Itu hanya tebakan. Anda mungkin bisa mendapatkan teks dari item yang dipilih, lihat edit saya.
SwDevMan81

3
ComboBox.SelectedItemtidak memiliki properti yang disebut Text, tetapi Anda dapat melakukannya ComboBox.SelectedItem as string(meskipun ini hanya dapat berfungsi jika Anda menggunakan stringuntuk Items- tidak menguji hal lain)
musefan

1
Hanya string teks = (string) e.AddedItems [0];
Igor Semin

1
Seandainya saya bisa menyerah 2, jawaban Anda membantu saya dua kali dalam 2 kesempatan berbeda
Upulie Han

59

Nilai yang benar untuk diperiksa di sini adalah properti SelectedItem .

ComboBox adalah kontrol gabungan dengan dua bagiannya adalah:

  1. Teks Bagian : nilai di bagian ini berkorespondensi dengan Teks milik ComboBox.
  2. Bagian Selector (yaitu bagian "drop-down"): Item yang dipilih di bagian ini sesuai dengan properti SelectedItem .

Bagian ComboBox yang Diperluas

Gambar di atas diambil segera setelah ComboBox diperluas (yaitu sebelum memilih nilai baru). Pada titik ini Text dan SelectedItem adalah "Info", dengan asumsi item ComboBox adalah string. Jika item ComboBox adalah semua nilai Enum yang disebut "LogLevel", SelectedItem saat ini akan menjadi LogLevel.Info .

Ketika sebuah item di drop-down diklik, nilai SelectedItem berubah dan event SelectionChanged dimunculkan. The Text properti tidak diperbarui lagi, meskipun, sebagai Teks Bagian tidak diperbarui sampai setelah SelectionChanged handler selesai. Ini dapat diamati dengan meletakkan breakpoint di pawang dan melihat kontrol:

ComboBox pada breakpoint di handler SelectionChanged

Karena Bagian Teks belum diperbarui pada saat ini, properti Teks mengembalikan nilai yang dipilih sebelumnya.


2
Ekspansi lengkap dan itu membantu mewujudkan Pengikatan saya berada di properti Teks alih-alih SelectedItem yang benar.
cmousset

1
@DaveKidder Contoh yang bagus! +1
Ryan Wilson

47

Gunakan acara DropDownClosed daripada selectionChanged jika Anda menginginkan nilai saat ini dari kotak kombo.

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

Sesederhana itu.


10
@jvelez Saya pikir itu tidak akan menyala saat menggunakan keyboard.
NoviceProgrammer

itu menyebalkan. Pemrogram pemula yang tahu ...!
tersembunyi

10

Ini berhasil untuk saya:

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

entah bagaimana hanya SelectedItem yang diisi dengan item baru, bukan SelectedValue.
mauris

7

Ini berhasil untuk saya:

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

Ini sangat penting. Jawaban yang diterima tidak secara eksplisit menunjukkan bahwa senderberisi jawaban yang benar SelectedItem.
Jess

4

Acara berikut diaktifkan untuk setiap perubahan teks di ComboBox (ketika indeks yang dipilih diubah dan ketika teks diubah dengan mengedit juga).

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

1
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}

6
Harap jangan berikan jawaban hanya kode. Tolong beri penjelasan mengapa solusi Anda adalah jawabannya.
Lee Taylor

1

Opsi kedua tidak berfungsi untuk saya karena elemen .Teks berada di luar cakupan (C # 4.0 VS2008). Ini adalah solusi saya ...

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

0

Saya perlu menyelesaikan ini di VB.NET. Inilah yang saya dapatkan yang sepertinya berhasil:

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

Aneh sekali SelectedItem menyimpan data baru, sedangkan SelectedValue tidak. Kedengarannya seperti bug bagi saya. Jika item Anda di Combobox adalah objek selain ComboBoxItems, Anda akan membutuhkan sesuatu seperti ini: (my ComboBoxcontains KeyValuePairs)

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.SelectedItemdapat menjadi null, sedangkan Visual Studio terus memberi tahu saya bahwa a KeyValuePairtidak dapat menjadi null. Itu sebabnya saya mentransmisikan SelectedItemke nullable KeyValuePair<string, string>?. Lalu saya periksa apakah selectedItemmemiliki nilai selain null. Pendekatan ini harus dapat diterapkan pada jenis item apa pun yang Anda pilih sebenarnya.


0

Jika Anda benar-benar membutuhkan SelectionChangedacara tersebut, maka jawaban terbaik adalah jawaban SwDevMan81. Namun, jika Anda memulai dengan WPF, maka Anda mungkin ingin mempelajari cara melakukan sesuatu dengan cara WPF, yang berbeda dari hari-hari Windows Forms lama yang dulu mengandalkan peristiwa seperti SelectionChanged, dengan WPF dan pola ViewModel Tampilan Model, Anda harus gunakan binding. Berikut adalah contoh kode:

// 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"); }
    }

}

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

Penggunaan e.AddedItems[0] as kProjectwhere kProject adalah kelas yang menyimpan data yang berfungsi untuk saya karena defaultnya ke RemovedItems [0] sebelum saya membuat perbedaan eksplisit ini. Terima kasih SwDevMan81 atas informasi awal yang menjawab pertanyaan ini untuk saya.


0

Jangan mempersulit sesuatu tanpa alasan. Menggunakan properti SelectedValue Anda bisa dengan mudah mendapatkan nilai ComboBox yang dipilih seperti ini: YourComboBoxName.SelectedValue.ToString ().

Di balik layar, properti SelectedValue didefinisikan sebagai: SelectedValue {get; set;} ini berarti Anda bisa menggunakannya untuk mendapatkan atau menyetel nilai ComboBox.

Menggunakan SelectedItem bukanlah cara yang efisien untuk mendapatkan nilai ComboBox karena membutuhkan banyak konsekuensi.


0

Anda dapat memeriksa properti SelectedIndex atau SelectedValue atau SelectedItem dalam acara SelectionChanged kontrol Combobox.


-2

Ini seharusnya berhasil untuk Anda ...

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

2
Bisakah Anda menjelaskan bagaimana ini menjawab pertanyaan?
Nathan Tuggy

-3

Saya menyelesaikan ini dengan menggunakan acara DropDownClosed karena ini menyala sedikit setelah nilainya diubah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.