ComboBox- SelectionChanged事件具有旧值,而不是新值


90

C#、. NET 4.0,VS2010。

WPF的新手。我的MainWindow上有一个ComboBox。我迷上了所述组合框的SelectionChanged事件。但是,如果我在事件处理程序中检查组合框的值,则它具有旧值。这听起来更像是“ SelectionChanging”事件,而不是SelectionChanged事件。

实际发生选择后,如何获得ComboBox的新值?

目前:

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

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

注意,如果我使用在事件args egeOriginalSource事件中传递的对象,则会得到相同的行为。


2
我偶然发现了同一问题-谢谢!那实际上是一个错误,它应该SelectionChanging首先被命名吗?
一月

Answers:


109

根据MSDN, e.AddedItems

获取包含所选项目的列表。

因此,您可以使用:

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

您也可以使用 SelectedItem如果您使用的stringItems来自,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具有旧的。该事件名称有点用词不当,至少是恕我直言。当我看到SelectionChanged时,我希望对象的状态已经改变。我可以看到这如何为我们提供更多信息。
马特2010年

1
是的,我认为是因为更改已发生,但尚未落实?那只是一个猜测。您可能可以获取所选项目的文本,请参见我的编辑。
SwDevMan81 2010年

3
ComboBox.SelectedItem没有名为的属性Text,但是您可以做到ComboBox.SelectedItem as string(尽管只有在string用于Items-而不测试其他属性的情况下,这才可能起作用)
musefan 2013年

只是字符串文本=(string)e.AddedItems [0];
伊戈尔·塞米

不要无缘无故地使事情复杂化。使用SelectedValue属性,您可以轻松地获得选定的ComboBox值,如下所示:YourComboBoxName.SelectedValue.ToString()。在后台,SelectedValue属性定义为:SelectedValue {get; set;};这意味着您可以使用它来获取或设置ComboBox的值。使用SelectedItem并不是获得ComboBox值的有效方法,因为它需要很多分支。
Sam Tomashi

59

这里要检查的正确值是SelectedItem属性。

ComboBox是一个复合控件,其两个部分为:

  1. 文本部分:此部分中的值对应于ComboBox 的Text属性。
  2. 选择器部分(即“下拉”部分):此部分中的选定项目对应于SelectedItem属性。

扩展的组合框零件

上面的图像是在ComboBox展开后立即拍摄的(即,在选择新值之前)。此时,假设ComboBox项是字符串,则TextSelectedItem均为“ Info”。如果ComboBox项是名为“ LogLevel”的枚举的所有值,则SelectedItem当前为 LogLevel.Info

单击下拉菜单中的项目时,SelectedItem的值将更改,并且将引发SelectionChanged事件。但是,Text属性尚未更新,因为Text Part直到SelectionChanged处理程序完成后才更新。可以通过在处理程序中放置一个断点并查看控件来观察到这一点:

在SelectionChanged处理程序中的断点处的ComboBox

由于此时尚未更新Text Part,因此Text属性将返回先前选择的值。


2
完全扩展,它有助于实现我的Binding位于Text属性上,而不是正确的SelectedItem。
cmousset

1
@DaveKidder很好的例子!+1
瑞安·威尔逊

46

如果需要组合框的当前值,请使用DropDownClosed事件而不是selectionChanged事件。

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

真的那么简单。


10
@jvelez我认为使用键盘时不会触发。
NoviceProgrammer 2011年

糟透了。知道...的新手程序员!!
隐藏

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
杰西

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
请不要提供仅代码的答案。请说明为什么您的解决方案是答案。
李·泰勒

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没有。对我来说听起来像个虫子。如果组合框中的项目不是ComboBoxItems的对象,则将需要类似以下内容:(我ComboBox包含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一直告诉我a KeyValuePair不能为null。这就是为什么我将SelectedItem强制转换为nullable的原因KeyValuePair<string, string>?。然后,我检查是否selectedItem具有非的值null。此方法应适用于您选择的项目实际上是什么类型。


0

如果您确实需要该SelectionChanged事件,则最佳答案是SwDevMan81的答案。但是,如果您是从WPF开始的,那么您可能想学习如何以WPF的方式进行操作,这与过去依靠诸如SelectionChangedWPF和Model View ViewModel模式等事件的Windows Forms时代不同,您应该使用绑定。这是一个代码示例:

// 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; set;},这意味着您可以使用它来获取或设置ComboBox的值。

使用SelectedItem并不是获得ComboBox值的有效方法,因为它需要很多分支。


0

您可以在Combobox控件的SelectionChanged事件中检查SelectedIndex或SelectedValue或SelectedItem属性。


-2

这应该为您工作...

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

2
您能解释一下如何回答这个问题吗?
内森·塔吉

-3

我通过使用DropDownClosed事件解决了此问题,因为更改值后此事件会稍微触发。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.