ComboBox- SelectionChanged 이벤트에 새 값이 아닌 이전 값이 있습니다.


91

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입니까?

답변:


110

MSDN에 따르면 e.AddedItems:

선택한 항목이 포함 된 목록을 가져옵니다.

따라서 다음을 사용할 수 있습니다.

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

당신은 또한 사용할 수 있습니다 SelectedItem당신이 사용하는 경우 string값을 Items로부터 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있는 개체, 안전한 방법은 사용하는 것 .ToString()대신에as string


11
흥미 롭습니다 ... 새로운 가치가 있습니다. 그리고 RemovedItems에는 이전 항목이 있습니다. 그 이벤트 이름은 적어도 IMHO라는 잘못된 이름이라면 약간입니다. SelectionChanged가 표시되면 개체의 상태가 변경된 것으로 예상됩니다. 이것이 어떻게 우리에게 약간 더 많은 정보를 제공하는지 알 수 있습니다.
Matt

1
그래, 변화가 발생했기 때문이라고 생각하지만 약속하지 않았습니까? 그것은 단지 추측입니다. 선택한 항목의 텍스트를 얻을 수 있습니다. 내 편집 내용을 참조하십시오.
SwDevMan81

3
ComboBox.SelectedItem속성 호출이없는 Text,하지만 당신은 할 수있다 ComboBox.SelectedItem as string(당신이 사용하는 경우에만 동작 할 수 있지만 string을 위해 Items- 다른되지 테스트 아무것도)
musefan

1
문자열 텍스트 = (문자열) e.AddedItems [0];
Igor Semin 2015 년

1
두 번 포기할 수 있기를 바랍니다. 귀하의 답변은 두
번의

59

여기서 확인할 올바른 값은 SelectedItem입니다. 속성입니다.

ComboBox는 다음과 같은 두 부분으로 구성된 복합 컨트롤입니다.

  1. 텍스트 부분 :이 부분의 값은 텍스트에 해당합니다. 은 ComboBox 속성에 해당합니다.
  2. 선택기 부분 (예 : "드롭 다운"부분) :이 부분에서 선택된 항목은 SelectedItem 속성에 해당 합니다.

확장 된 ComboBox 부품

위의 이미지는 ComboBox가 확장 된 직후 (즉, 새 값을 선택하기 전에) 찍은 것입니다. 이 시점 에서 ComboBox 항목이 문자열이라고 가정하면 TextSelectedItem 은 모두 "Info"입니다. 대신 ComboBox 항목이 "LogLevel"이라는 Enum의 모든 값이면 SelectedItem 은 현재 LogLevel.Info가 됩니다.

드롭 다운의 항목을 클릭하면 SelectedItem 의 값 이 변경되고 SelectionChanged 이벤트가 발생합니다. 그러나 Text 속성은 SelectionChanged 처리기가 완료 될 때까지 텍스트 부분 이 업데이트되지 않으므로 아직 업데이트되지 않았습니다 . 핸들러에 중단 점을 넣고 컨트롤을 보면이를 확인할 수 있습니다.

SelectionChanged 처리기의 중단 점에있는 ComboBox

때문에 텍스트 부분이 이 시점에서 업데이트되지 않았습니다의 텍스트 속성은 이전에 선택한 값을 반환합니다.


2
확장을 완료하고 내 Binding이 올바른 SelectedItem 대신 Text 속성에 있음을 깨닫는 데 도움이되었습니다.
cmousset

1
@DaveKidder 좋은 예! 한
라이언 윌슨

47

콤보 상자의 현재 값을 원하는 경우 selectionChanged 대신 DropDownClosed 이벤트를 사용하십시오.

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

정말 간단합니다.


10
@jvelez 키보드를 사용할 때 실행되지 않을 것이라고 생각합니다.
NoviceProgrammer

짜증나. 알고 있던 초보자 프로그래머 ...!
숨김

10

이것은 나를 위해 일했습니다.

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

어떻게 든 SelectedItem 만 SelectedValue가 아닌 새 항목으로 채워집니다.
mauris 2013-08-23

7

이것은 나를 위해 일했습니다.

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

이건 매우 중요합니다. 허용되는 답변은 sender올바른 SelectedItem.
Jess

4

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

6
코드 전용 답변을 제공하지 마십시오. 귀하의 솔루션이 답인 이유를 설명해주십시오.
Lee Taylor

1

두 번째 옵션은 .Text 요소가 범위를 벗어 났기 때문에 작동하지 않았습니다 (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

SelectedItem이 새로운 데이터를 보유하는 반면 SelectedValue는 그렇지 않다는 것이 이상합니다. 나에게 버그처럼 들린다. 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.SelectedItemVisual Studio는 a KeyValuePair가 null이 될 수 없다고 계속 알려 줍니다. SelectedItem그래서을 nullable로 캐스트합니다 KeyValuePair<string, string>?. 그런 다음 selectedItem다른 값이 있는지 확인합니다 null. 이 접근 방식은 선택한 항목이 실제로 어떤 유형이든 적용 가능해야합니다.


0

정말 SelectionChanged이벤트 가 필요한 경우 가장 좋은 답변은 SwDevMan81의 답변입니다. 그러나 WPF로 시작하는 경우 SelectionChangedWPF 및 Model View ViewModel 패턴 을 사용하여와 같은 이벤트에 의존하는 이전 Windows Forms 시대와 다른 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 속성을 사용하면 YourComboBoxName.SelectedValue.ToString ()과 같이 선택한 ComboBox 값을 쉽게 얻을 수 있습니다.

이면에서 SelectedValue 속성은 다음과 같이 정의됩니다. SelectedValue {get; set;} 이것은 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.