web-dev-qa-db-ja.com

ComboBox- SelectionChangedイベントには古い値があり、新しい値はありません

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

注:イベント引数で渡されるオブジェクトを使用する場合、同じ動作になります。 e.OriginalSource。

83
Matt

MSDNによると、 e.AddedItems

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

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

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

SelectedItemstringItems値を使用する場合は、senderを使用することもできます。

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は両方ともオブジェクトなので、より安全なアプローチはas stringの代わりに.ToString()を使用することです。

98
SwDevMan81

ここで確認する正しい値は、SelectedItemプロパティです。

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

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

Expanded ComboBox Parts

上記の画像は、ComboBoxが展開された直後(つまり、新しい値を選択する前)に撮影されたものです。この時点で、TextSelectedItemは両方とも「Info」です。 ComboBoxアイテムは文字列でした。 ComboBoxアイテムが「LogLevel」というEnumのすべての値であった場合、SelectedItemは現在LogLevelになります。情報

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

ComboBox at breakpoint in SelectionChanged handler

Text Partはこの時点では更新されていないため、Textプロパティは、以前に選択した値を返します。

50
Dave Kidder

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

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

本当に簡単ですか。

46
hidden

これは私のために働いた:

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

これは私のために働いた:

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

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

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />
2
Petr Voborník

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

string test = null;
foreach (ComboBoxItem item in e.AddedItems)
{
   test = item.Content.ToString();
   break;
}
1
Josh
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}
1
Buratino

SelectionChangedイベントが本当に必要な場合、最善の答えはSwDevMan81の答えです。ただし、WPFで開始する場合は、WPFおよびモデルビューでSelectionChangedなどのイベントに依存していた古いWindowsフォームの時代とは異なる、WPFの方法で物事を行う方法を学びたい場合があります。 ViewModelパターン、バインディングを使用する必要があります。コード例を次に示します。

// 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
Lazaro

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

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

0
kyjote

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
zzMzz

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

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

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

0
Sam Tomashi