Подтвердить что ты не робот

Событие ComboBox - SelectionChanged имеет старое значение, а не новое значение

С#,.NET 4.0, VS2010.

Новое для WPF. У меня есть ComboBox на моем MainWindow. Я подключил событие SelectionChanged указанного поля со списком. Однако, если я рассмотрю значение поля со списком в обработчике событий, оно имеет старое значение. Это скорее похоже на событие SelectionChanging, чем событие SelectionChanged.

Как получить новое значение ComboBox после того, как выбор действительно наступил?

В настоящее время

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

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

Обратите внимание: я получаю такое же поведение, если я использую объект, передаваемый в аргументах события, например. e.OriginalSource.

4b9b3361

Ответ 1

Согласно 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;
}

Поскольку оба Content и SelectedItem являются объектами, более безопасным подходом было бы использовать .ToString() вместо as string

Ответ 2

Используйте событие DropDownClosed вместо selectionChanged, если вы хотите использовать текущее значение поля со списком.

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

Действительно, это просто.

Ответ 3

Правильное значение для проверки здесь - это свойство SelectedItem.

ComboBox представляет собой составное управление с двумя его частями:

  • Текстовая часть: значение в этой части соответствует свойству Текст ComboBox.
  • Селекторная часть (т.е. часть раскрывающегося списка): выбранный элемент в этой части соответствует свойству SelectedItem.

Расширенные компоненты ComboBox

Изображение выше было сделано сразу же после того, как ComboBox был расширен (т.е. перед выбором нового значения). На данный момент как Текст, так и SelectedItem являются "Информация", предполагая, что элементы ComboBox были строками. Если элементы ComboBox были вместо всех значений Enum, называемых "LogLevel", SelectedItem в настоящее время будет LogLevel.Info.

Когда элемент в раскрывающемся списке нажат, значение Выбранный элемент будет изменен, и будет добавлено событие SelectionChanged. Свойство Текст еще не обновлено, поскольку Текстовая часть не обновляется до тех пор, пока обработчик SelectionChanged не будет завершен. Это можно наблюдать, поставив точку останова в обработчике и посмотрев на элемент управления:

ComboBox в точке останова в обработчике SelectionChanged

Поскольку Текстовая часть не была обновлена ​​в этот момент, свойство Текст возвращает ранее выбранное значение.

Ответ 4

Это сработало для меня:

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

Ответ 5

Это сработало для меня:

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

Ответ 6

Следующее событие запускается для любого изменения текста в ComboBox (при изменении выбранного индекса и изменении текста с помощью редактирования).

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

Ответ 7

Второй вариант не работал у меня, потому что элемент .Text был недоступен (С# 4.0 VS2008). Это было мое решение...

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

Ответ 8

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}

Ответ 9

Мне нужно было решить это на 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

Ответ 10

Странно, что SelectedItem содержит свежие данные, а SelectedValue - нет. Звучит как ошибка. Если ваши элементы в Combobox являются объектами, отличными от ComboBoxItems, вам понадобится что-то вроде этого: (my ComboBox содержит KeyValuePair s)

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<string, string>?. Затем я проверяю, имеет ли значение SelectedItem значение, отличное от null. Этот подход должен быть применим к любому типу, выбранному вами на самом деле.

Ответ 11

Если вам действительно нужно событие SelectionChanged, лучшим ответом будет ответ SwDevMan81. Однако, если вы начинаете с WPF, вам может захотеть узнать, как делать вещи с помощью WPF, который отличается от старых дней Windows Forms, которые использовали для использования таких событий, как SelectionChanged, с WPF и Model View ViewModel pattern, вы должны использовать привязки. Вот пример кода:

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

}

Ответ 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().

set;} это означает, что вы можете использовать его для получения или установки значения ComboBox.

Использование SelectedItem не является эффективным способом получения значения ComboBox, так как требует много последствий.

Ответ 14

    private void comboBox_Change(object sender, SelectionChangedEventArgs e)
    {
        string item = ((sender as ComboBox).SelectedItem as TextBlock).Text;
    }

Ответ 15

Это должно сработать для вас...

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

Ответ 16

Я решил это, используя событие DropDownClosed, потому что это немного ускорилось после изменения значения.