【问题标题】:ComboBox- SelectionChanged event has old value, not new valueComboBox- SelectionChanged 事件具有旧值,而不是新值
【发布时间】:2010-06-02 19:53:10
【问题描述】:

C#、.NET 4.0、VS2010。

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

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

目前:

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

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

注意,如果我使用在事件参数中传递的对象,我会得到相同的行为,例如e.原始来源。

【问题讨论】:

  • 我偶然发现了同样的问题 - 谢谢!这实际上是一个错误吗?首先应该将其命名为 SelectionChanging
  • 检查 ComboBox.OnSelectionChanged 方法的源代码表明它发布了事件并然后处理了选定的项目。 In a related problem,我使用反射强制它处理来自我的 SelectionChanged 事件处理程序的选定项目。

标签: c# wpf combobox .net-4.0 selectionchanged


【解决方案1】:

根据 MSDN,e.AddedItems

获取包含已选择项目的列表。

所以你可以使用:

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

如果您使用来自senderItemsstring 值,您也可以使用SelectedItem

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

【讨论】:

  • 有趣...它具有新的价值。而 RemovedItems 有旧的。该事件名称有点用词不当,至少恕我直言。当我看到 SelectionChanged 时,我预计对象的状态会发生变化。不过,我可以看到这如何为我们提供了更多信息。
  • 是的,我认为是因为更改已经发生,但尚未提交?那只是一个猜测。您也许可以获取所选项目的文本,请参阅我的编辑。
  • ComboBox.SelectedItem 没有名为Text 的属性,但您可以使用ComboBox.SelectedItem as string(尽管这可能仅在您使用stringItems 时才有效 - 未测试任何其他内容)
  • 只是字符串文本 = (string)e.AddedItems[0];
  • 希望我能给 2 个 ups,你的回答在 2 个不同的场合帮助了我两次
【解决方案2】:

此处要检查的正确值是 SelectedItem 属性。

ComboBox 是一个复合控件,它的两个部分是:

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

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

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

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

【讨论】:

  • 完成扩展,它帮助我意识到我的 Binding 是在 Text 属性上而不是正确的 SelectedItem 上。
  • @DaveKidder 很好的例子! +1
【解决方案3】:

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

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

真的就这么简单。

【讨论】:

  • @jvelez 我认为使用键盘时它不会触发。
  • 太糟糕了。知道...的新手程序员!
  • 这对我有用。 It is comical that it's not possible to easily get the selected value when the selection has changed.我相信这是有充分理由的,但是天哪。
【解决方案4】:

这对我有用:

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

【讨论】:

  • 不知何故只有 SelectedItem 被新项目填充,而不是 SelectedValue。
【解决方案5】:

这对我有用:

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

【讨论】:

  • 这很重要。接受的答案没有明确表明sender 包含正确的SelectedItem
  • 这给我抛出了一个异常: System.NullReferenceException: '对象引用未设置为对象的实例。' (... as System.Windows.Controls.ComboBoxItem) 返回 null。
  • @Jess - 我 100% 同意。接受的答案对我不起作用。这个做到了。
【解决方案6】:

在Combobox中为文本的任何更改而触发事件之后(当更改所选索引以及文本也通过编辑更改时)。

)。
<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />

【讨论】:

    【解决方案7】:
    private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
    {
        string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
    }
    

    【讨论】:

    • 请不要提供纯代码的答案。请解释为什么您的解决方案是答案。
    • System.InvalidCastException: '无法将'System.String'类型的对象转换为'System.Data.DataRowView'类型。'
    【解决方案8】:

    第二个选项对我不起作用,因为 .Text 元素超出了范围(C# 4.0 VS2008)。这是我的解决方案...

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

    【讨论】:

      【解决方案9】:

      如果你真的需要SelectionChanged 事件,那么最好的答案就是 SwDevMan81 的答案。但是,如果您从 WPF 开始,那么您可能想学习如何以 WPF 方式做事,这与过去使用 WPF 和模型视图 ViewModel 模式依赖于 SelectionChanged 等事件的旧 Windows 窗体时代不同,你应该使用绑定。这是一个代码示例:

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

      【讨论】:

        【解决方案10】:

        我需要在 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
        

        【讨论】:

          【解决方案11】:

          奇怪的是,SelectedItem 拥有新数据,而 SelectedValue 却没有。对我来说听起来像是一个错误。如果您在 Combobox 中的项目是 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 可以为空,而 Visual Studio 一直告诉我 KeyValuePair 不能为空。这就是我将SelectedItem 转换为可为空的KeyValuePair&lt;string, string&gt;? 的原因。然后我检查selectedItem 的值是否不是null。这种方法应该适用于您选择的项目实际上是什么类型。

          【讨论】:

            【解决方案12】:
            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 为我回答了这个问题的初步信息。

            【讨论】:

              【解决方案13】:

              不要无缘无故地把事情复杂化。使用 SelectedValue 属性,您可以轻松获取选定的 ComboBox 值,如下所示:YourComboBoxName.SelectedValue.ToString()。

              在幕后,SelectedValue 属性定义为:SelectedValue{get; set;} 这意味着您可以使用它来获取或设置 ComboBox 的值。

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

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                  【解决方案15】:

                  从组合框的 SelectionChanged 事件中,您可以获得所选项目的文本,如下所示:

                          private void myComboBox_SelectionChanged (object sender, SelectionChangedEventArgs e)
                          {
                          ComboBoxItem comboBoxItem = (ComboBoxItem) e.AddedItems[0];
                          string selectedItemText = comboBoxItem.Content.ToString();
                          }
                  

                  【讨论】:

                    【解决方案16】:

                    这应该适合你...

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

                    【讨论】:

                    • 你能解释一下这是如何回答这个问题的吗?
                    【解决方案17】:

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-10-22
                      • 2012-02-03
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-03-17
                      相关资源
                      最近更新 更多