ComboBox- SelectionChangedイベントには新しい値ではなく古い値があります


90

C#、. NET 4.0、VS2010。

WPFの新機能。MainWindowにComboBoxがあります。上記のコンボボックスのSelectionChangedイベントをフックしました。ただし、イベントハンドラーでコンボボックスの値を調べると、古い値になります。これは、SelectionChangedイベントではなく、「SelectionChanging」イベントのように聞こえます。

選択が実際に行われた後、ComboBoxの新しい値を取得するにはどうすればよいですか?

現在:

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

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

注:イベント引数で渡されるオブジェクト(egeOriginalSource)を使用しても、同じ動作が得られます。


2
同じ問題に遭遇しました-ありがとうございます!それは実際にバグSelectionChangingですか、そもそも名前が付けられているはずですか?

回答:


109

MSDNによると、e.AddedItems

選択された項目を含むリストを取得します。

だからあなたは使うことができます:

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

fromの値を使用するSelectedItem場合にも使用できます。stringItemssender

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

または

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

ContentSelectedItemはどちらもオブジェクトであるため、より安全な方法は.ToString()as string


11
興味深い...それは新しい価値を持っています。そして、RemovedItemsは古いです。そのイベント名は、少なくとも私見では誤称です。SelectionChangedが表示されたら、オブジェクトの状態が変更されたはずです。ただし、これにより少し多くの情報が得られることがわかります。
Matt

1
ええ、私はそれが変化が起こったからだと思いますが、コミットされていませんか?それは単なる推測です。選択したアイテムのテキストを取得できる場合があります。私の編集を参照してください。
SwDevMan81 2010年

3
ComboBox.SelectedItemにはと呼ばれるプロパティはありませんが、Text実行できますComboBox.SelectedItem as string(ただし、これはに使用stringした場合にのみ機能する可能性がありますItems-他には何もテストしていません)
musefan

文字列text =(string)e.AddedItems [0];
Igor Semin 2015年

理由もなく複雑にしないでください。SelectedValueプロパティを使用すると、次のような選択されたComboBox値を簡単に取得できます:YourComboBoxName.SelectedValue.ToString()。舞台裏では、SelectedValueプロパティは次のように定義されています:SelectedValue {get; これは、ComboBoxの値を取得または設定するために使用できることを意味します。SelectedItemの使用は、多くの影響を必要とするため、ComboBox値を取得する効率的な方法ではありません。
Sam Tomashi

59

ここでチェックする正しい値はSelectedItemプロパティです。

ComboBoxは、次の2つの部分を持つ複合コントロールです。

  1. テキスト部分:この部分の値は、ComboBoxのTextプロパティに対応します。
  2. セレクタパーツ(「ドロップダウン」パーツ):このパーツで選択されたアイテムは、SelectedItemプロパティに対応します。

拡張されたComboBoxパーツ

上の画像は、ComboBoxが展開された直後(つまり、新しい値を選択する前)のものです。この時点では、ComboBoxアイテムが文字列であると想定して、TextSelectedItemはどちらも「Info」です。ComboBoxアイテムが「LogLevel」と呼ばれるEnumのすべての値である場合、SelectedItemは現在LogLevel.Infoになります。

ドロップダウンの項目をクリックすると、SelectedItemの値が変更され、SelectionChangedイベントが発生します。テキストプロパティは、しかし、まだ更新されていないとして、一部はテキストの後まで更新されませんSelectionChangedハンドラが終了します。これは、ハンドラーにブレークポイントを設定し、コントロールを確認することで確認できます。

SelectionChangedハンドラーのブレークポイントにあるComboBox

以来テキストパートが、この時点で更新されていない、テキストプロパティは、以前に選択した値を返します。


2
完全な展開により、バインディングが正しいSelectedItemではなくTextプロパティにあることがわかりました。
cmousset 2015年

1
@DaveKidder素晴らしい例!+1
ライアンウィルソン

46

コンボボックスの現在の値が必要な場合は、selectionChangedの代わりにDropDownClosedイベントを使用します。

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

本当にそんなに簡単です。


10
@jvelezキーボードを使用しても起動しないと思います。
NoviceProgrammer '19

それは吸う。知っていた初心者プログラマ...!
2013

10

これは私のために働きました:

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

どういうわけか、SelectedItemだけがSelectedValueではなく、新しい項目で生成されます。
モーリス2013

7

これは私のために働きました:

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

これは非常に重要です。受け入れられた回答はsender、正しいを含むことを明示的に示していませんSelectedItem
Jess

3

次のイベントは、ComboBox内のテキストが変更されると発生します(選択されたインデックスが変更されたとき、および編集によってテキストが変更されたとき)。

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

5
コードのみの回答は提供しないでください。ソリューションが答えである理由を説明してください。
Lee Taylor

1

.Text要素が範囲外だったため、2番目のオプションは機能しませんでした(C#4.0 VS2008)。これが私の解決策でした...

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

0

これをVB.NETで解決する必要がありました。これがうまくいくように私が持っているものです:

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

SelectedValueが新しいデータを保持するのに対し、SelectedItemが新しいデータを保持するのは奇妙です。私にはバグのように聞こえます。ComboboxのアイテムがComboBoxItems以外のオブジェクトである場合、次のようなものが必要になります:(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.SelectedItemnullにすることができますが、Visual StudioはKeyValuePairnullにできないことを通知し続けます。そのため、私SelectedItemはnullable にキャストしKeyValuePair<string, string>?ます。次にselectedItem、以外の値があるかどうかを確認しますnull。このアプローチは、選択したアイテムが実際にどんなタイプでも適用できるはずです。


0

SelectionChangedイベントが本当に必要な場合、最良の答えはSwDevMan81の答えです。ただし、WPFで開始する場合はSelectionChanged、WPFとモデルビューのViewModelパターンを使用して、のようなイベントに依存するために使用されていた古いWindowsフォームの日とは異なる、WPFの方法を実行する方法を学ぶことができます。バインディングを使用します。次にコード例を示します。

// 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 kProjectwhere kProject の使用は、この明確な区別をする前に、デフォルトでRemovedItems [0]に設定されていたため、私のために機能するデータを保持するクラスです。私のためにこの質問に答えた最初の情報をSwDevMan81に感謝します。


0

理由もなく複雑にしないでください。SelectedValueプロパティを使用すると、次のような選択されたComboBox値を簡単に取得できます:YourComboBoxName.SelectedValue.ToString()。

舞台裏では、SelectedValueプロパティは次のように定義されています:SelectedValue {get; これは、ComboBoxの値を取得または設定するために使用できることを意味します。

SelectedItemの使用は、多くの影響を必要とするため、ComboBox値を取得する効率的な方法ではありません。


0

ComboboxコントロールのSelectionChangedイベントでSelectedIndexまたはSelectedValueまたはSelectedItemプロパティを確認できます。


-2

これはあなたのために働くはずです...

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

2
これがどのように質問に答えるかを説明できますか?
Nathan Tuggy 2015年

-3

これは、値が変更された後にわずかに発生するため、DropDownClosedイベントを使用して解決しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.