ComboBox- SelectionChanged olayının yeni değeri değil eski değeri var


91

C #, .NET 4.0, VS2010.

WPF'de yeni. MainWindow'umda bir ComboBox'ım var. Söz konusu birleşik giriş kutusunun SelectionChanged olayını bağladım. Ancak, olay işleyicisindeki açılan kutunun değerini incelersem, eski değerine sahip olur. Bu, bir SelectionChanged olayından çok "SelectionChanging" olayına benziyor.

Seçim gerçekten gerçekleştikten sonra ComboBox'ın yeni değerini nasıl elde edebilirim?

Şu anda:

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

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

Not, olay değiştirgelerinde (egeOriginalSource) iletilen nesneyi kullanırsam aynı davranışı elde ederim.


2
Ben de aynı sorunla karşılaştım - teşekkürler! Bu aslında bir hata mı SelectionChangingve ilk başta adlandırılmış olması gerekir mi?
Jan

Yanıtlar:


110

MSDN'ye göre e.AddedItems:

Seçilen öğeleri içeren bir liste alır.

Böylece şunları kullanabilirsiniz:

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

Ayrıca kullanabilirsiniz SelectedItemkullanırsanız stringdeğerlerini Itemsdan sender:

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

veya

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

Her iki yana Contentve SelectedItemnesnelerin, daha güvenli bir yaklaşım kullanmak olacaktır .ToString()yerineas string


11
ilginç ... yeni bir değere sahip. Ve RemovedItems eskiye sahiptir. Bu olay adı biraz yanlış bir isim, en azından IMHO. SelectionChanged'i gördüğümde, nesnenin durumunun değişmesini bekliyorum. Bunun bize nasıl biraz daha fazla bilgi verdiğini görebiliyorum.
Matt

1
Evet, bence değişimin gerçekleşmiş olması, ancak taahhüt edilmemesi nedeniyle mi? Bu sadece bir tahmin. Seçili öğenin metnini alabilirsiniz, düzenlememe bakın.
SwDevMan81

3
ComboBox.SelectedItemadlı bir mülk Textyok, ancak yapabilirsiniz ComboBox.SelectedItem as string(bu yalnızca stringiçin kullanırsanız işe yarayabilir Items- başka hiçbir şey test edilmemiştir)
musefan

1
Sadece string text = (string) e.AddedItems [0];
Igor Semin

1
Keşke 2 şey
verebilseydim

59

Burada kontrol edilecek doğru değer SelectedItem özelliğidir.

ComboBox, iki parçası olan bileşik bir kontroldür:

  1. Metin Bölümü : Bu bölümdeki değer , ComboBox öğesinin Text özelliğine karşılık gelir .
  2. Seçici Kısım (yani "açılır" kısım): Bu kısımdaki seçilen öğe SelectedItem özelliğine karşılık gelir .

Genişletilmiş ComboBox Parçaları

Yukarıdaki resim, ComboBox genişletildikten hemen sonra (yani yeni bir değer seçilmeden önce) çekilmiştir. Bu noktada hem Metin ve SelectedItem ComboBox birimler dizi olmadığı varsayılır "Bilgi" dir. ComboBox öğeleri bunun yerine "LogLevel" adlı bir Enum'un tüm değerleri olsaydı , SelectedItem şu anda LogLevel.Info olurdu .

Açılır menüdeki bir öğeye tıklandığında, SelectedItem değeri değiştirilir ve SelectionChanged olayı başlatılır . Metin özelliği olsa da, henüz güncellenmemiş gibi Bölüm Metin sonrasına kadar güncellenmez SelectionChanged işleyici bitti. Bu, işleyiciye bir kesme noktası koyarak ve denetime bakarak gözlemlenebilir:

SelectionChanged işleyicisinde kesme noktasında ComboBox

Yana Metin Parça bu noktada güncellenmedi, Metin özellik daha önce seçilen değeri döndürür.


2
Eksiksiz genişletme ve Binding'imin doğru SelectedItem yerine Text özelliğinde olduğunun farkına varılmasına yardımcı oldu.
cmousset

1
@DaveKidder Harika bir örnek! +1
Ryan Wilson

47

Birleşik giriş kutusunun geçerli değerini istiyorsanız, selectionChanged yerine DropDownClosed olayını kullanın.

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

Gerçekten bu kadar basit.


10
@jvelez Klavye kullanırken ateşlenmeyeceğini düşünüyorum.
NoviceProgrammer

bu berbat. Acemi Programcı bilen ...!
gizlendi

10

Bu benim için çalıştı:

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

her nasılsa yalnızca SelectedItem yeni öğe ile doldurulur, SelectedValue ile değil.
mauris

7

Bu benim için çalıştı:

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

Bu çok önemli. Kabul edilen cevap, doğruyu senderiçerdiğini açıkça göstermez SelectedItem.
Jess

4

ComboBox'taki herhangi bir metin değişikliği için aşağıdaki olay tetiklenir (seçilen dizin değiştirildiğinde ve metin de düzenlenerek değiştirildiğinde).

<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
Lütfen yalnızca kod içeren yanıtlar vermeyin. Lütfen çözümünüzün neden cevap olduğuna dair bir açıklama yapın.
Lee Taylor

1

.Text öğesi kapsam dışında olduğundan ikinci seçenek benim için çalışmadı (C # 4.0 VS2008). Bu benim çözümümdü ...

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

0

Bunu VB.NET'te çözmem gerekiyordu. İşte işe yarayan şey var:

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

SelectedItem'in taze verileri tutması, SelectedValue'nun tutmaması tuhaf. Bana bir böcek gibi geldi. Combobox'taki öğeleriniz ComboBoxItems dışındaki nesneler ise, şuna benzer bir şeye ihtiyacınız olacaktır: (benimComboBox içerirlerim KeyValuePair)

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.SelectedItemboş olabilir, oysa Visual Studio bana KeyValuePaira'nın boş olamayacağını söylemeye devam ediyor . Bu yüzden SelectedItemnullable'a atıyorum KeyValuePair<string, string>?. Sonra selectedItemdışında bir değer olup olmadığını kontrol ederim null. Bu yaklaşım, seçtiğiniz öğenin gerçekte türü ne olursa olsun uygulanabilir olmalıdır.


0

SelectionChangedEtkinliğe gerçekten ihtiyacınız varsa , o zaman en iyi cevap SwDevMan81'in cevabıdır. Bununla birlikte, WPF ile başlıyorsanız SelectionChanged, WPF ve Model View ViewModel kalıbı gibi olaylara dayanan eski Windows Forms günlerinden farklı olan WPF yöntemini nasıl yapacağınızı öğrenmek isteyebilirsiniz. bağlamaları kullanın. İşte bir kod örneği:

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

e.AddedItems[0] as kProjectBurada kProject kullanımı, ben bu açık ayrımı yapmadan önce varsayılan olarak RemovedItems [0] 'a ayarlandığı için benim için çalışan verileri tutan bir sınıftır. Bu soruyu benim için yanıtlayan ilk bilgiler için SwDevMan81'e teşekkürler.


0

Sebepsiz yere işleri karıştırmayın. SelectedValue özelliğini kullanarak, aşağıdaki gibi seçilen bir ComboBox değerini kolayca alabilirsiniz: YourComboBoxName.SelectedValue.ToString ().

Sahnenin arkasında SelectedValue özelliği şu şekilde tanımlanır: SelectedValue {get; set;} bu, onu bir ComboBox değerini almak veya ayarlamak için kullanabileceğiniz anlamına gelir.

SelectedItem'i kullanmak, çok fazla sonuç gerektirdiğinden ComboBox değeri elde etmenin etkili bir yolu değildir.


0

Combobox denetiminin SelectionChanged olayında SelectedIndex veya SelectedValue veya SelectedItem özelliğini kontrol edebilirsiniz.


-2

Bu sizin için çalışmalı ...

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

2
Bunun soruyu nasıl yanıtladığını açıklayabilir misin?
Nathan Tuggy

-3

Bunu DropDownClosed olayını kullanarak çözdüm çünkü bu, değer değiştirildikten sonra biraz tetikleniyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.