Sự kiện ComboBox- SelectionChanged có giá trị cũ, không phải giá trị mới


90

C #, .NET 4.0, VS2010.

Mới đối với WPF. Tôi có một ComboBox trên MainWindow của mình. Tôi nối sự kiện SelectionChanged của hộp kết hợp nói trên. Tuy nhiên, nếu tôi kiểm tra giá trị của hộp tổ hợp trong trình xử lý sự kiện, nó có giá trị cũ. Điều này nghe giống sự kiện "SelectionChanged" hơn là sự kiện SelectionChanged.

Làm cách nào để nhận giá trị mới của ComboBox sau khi lựa chọn đã thực sự xảy ra?

Hiện tại:

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

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

Lưu ý, tôi nhận được hành vi tương tự nếu tôi sử dụng đối tượng đang được chuyển trong các args sự kiện, egeOriginalSource.


2
Tôi vừa vấp phải vấn đề tương tự - cảm ơn! Đó thực sự là một lỗi, và nó đáng lẽ phải được đặt tên SelectionChangingngay từ đầu?
Ngày

Câu trả lời:


109

Theo MSDN, e.AddedItems:

Nhận danh sách có chứa các mục đã được chọn.

Vì vậy, bạn có thể sử dụng:

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

Bạn cũng có thể sử dụng SelectedItemnếu bạn sử dụng stringcác giá trị cho Itemstừ sender:

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

hoặc là

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

Kể từ khi cả hai ContentSelectedItemlà những vật thể, một cách tiếp cận an toàn hơn sẽ được sử dụng .ToString()thay vìas string


11
thú vị ... nó có giá trị mới. Và RemovedItems có cái cũ. Tên sự kiện đó là một chút nếu viết sai, ít nhất là IMHO. Khi tôi nhìn thấy SelectionChanged, tôi hy vọng trạng thái của đối tượng, tốt, đã thay đổi. Tôi có thể thấy cách điều này cung cấp cho chúng tôi nhiều thông tin hơn một chút.
Matt

1
Vâng, tôi nghĩ đó là vì sự thay đổi đã xảy ra, nhưng không được cam kết? Đó chỉ là một phỏng đoán. Bạn có thể lấy văn bản của mục đã chọn, hãy xem chỉnh sửa của tôi.
SwDevMan81

3
ComboBox.SelectedItemkhông có thuộc tính được gọi là Text, nhưng bạn có thể làm ComboBox.SelectedItem as string(mặc dù điều này chỉ có thể hoạt động nếu bạn sử dụng stringcho Items- không được thử nghiệm bất kỳ thứ gì khác)
Shuifan

Chỉ chuỗi text = (string) e.AddedItems [0];
Igor Semin

Đừng phức tạp hóa mọi thứ mà không có lý do. Sử dụng thuộc tính SelectedValue, bạn có thể dễ dàng nhận được giá trị ComboBox đã chọn như sau: YourComboBoxName.SelectedValue.ToString (). Phía sau thuộc tính SelectedValue được định nghĩa là: SelectedValue {get; set;} điều này có nghĩa là bạn có thể sử dụng nó để lấy hoặc đặt giá trị của ComboBox. Sử dụng SelectedItem không phải là một cách hiệu quả để nhận giá trị ComboBox vì nó yêu cầu rất nhiều phân nhánh.
Sam Tomashi

59

Giá trị chính xác để kiểm tra ở đây là thuộc tính SelectedItem .

ComboBox là một điều khiển tổng hợp với hai phần của nó là:

  1. Phần Văn bản : giá trị trong phần này tương ứng với thuộc tính Văn bản của ComboBox.
  2. Phần Bộ chọn (tức là phần "thả xuống"): Mục được chọn trong phần này tương ứng với thuộc tính SelectedItem .

Bộ phận ComboBox mở rộng

Hình trên được chụp ngay sau khi ComboBox được mở rộng (tức là trước khi chọn một giá trị mới). Tại thời điểm này, cả TextSelectedItem đều là "Thông tin", giả sử các mục ComboBox là chuỗi. Nếu các mục ComboBox thay vào đó là tất cả các giá trị của Enum được gọi là "LogLevel", thì SelectedItem hiện sẽ là LogLevel.Info .

Khi một mục trong menu thả xuống được nhấp vào, giá trị của SelectedItem được thay đổi và sự kiện SelectionChanged được nâng lên. Các chữ tài sản không được cập nhật bài viết nào, tuy nhiên, như các chữ Phần không được cập nhật cho đến sau khi SelectionChanged xử lý xong. Điều này có thể được quan sát bằng cách đặt một điểm ngắt vào trình xử lý và nhìn vào điều khiển:

ComboBox tại điểm ngắt trong trình xử lý SelectionChanged

Phần Văn bản chưa được cập nhật vào thời điểm này, thuộc tính Văn bản trả về giá trị đã chọn trước đó.


2
Hết hạn hoàn thành và nó giúp nhận ra rằng Binding của tôi nằm trên thuộc tính Text thay vì SelectedItem chính xác.
cmousset

1
@DaveKidder Ví dụ tuyệt vời! +1
Ryan Wilson

46

Sử dụng sự kiện DropDownClosed thay vì selectChanged nếu bạn muốn giá trị hiện tại của hộp tổ hợp.

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

Thực sự là đơn giản.


10
@jprisz Tôi nghĩ rằng nó sẽ không kích hoạt khi sử dụng bàn phím.
NoviceProgrammer,

thật tệ. NoviceProgrammer ai biết ...!
ẩn

10

Điều này đã làm việc cho tôi:

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

bằng cách nào đó, chỉ SelectedItem mới được điền vào mục mới, không phải SelectedValue.
mauris

7

Điều này đã làm việc cho tôi:

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

Cái này rất quan trọng. Câu trả lời được chấp nhận không hiển thị rõ ràng câu trả lời senderđúng SelectedItem.
Jess

3

Sự kiện sau được kích hoạt cho bất kỳ thay đổi nào của văn bản trong ComboBox (khi chỉ mục đã chọn bị thay đổi và khi văn bản cũng được thay đổi bằng cách chỉnh sửa).

<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
Vui lòng không cung cấp câu trả lời chỉ có mã. Vui lòng đưa ra lời giải thích tại sao giải pháp của bạn là câu trả lời.
Lee Taylor

1

Tùy chọn thứ hai không hoạt động đối với tôi vì phần tử .Text nằm ngoài phạm vi (C # 4.0 VS2008). Đây là giải pháp của tôi ...

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

0

Tôi cần giải quyết vấn đề này trong VB.NET. Đây là những gì tôi có mà dường như hoạt động:

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

Thật kỳ lạ khi SelectedItem giữ dữ liệu mới, trong khi SelectedValue thì không. Nghe như một lỗi đối với tôi. Nếu các mục của bạn trong Combobox là các đối tượng khác với ComboBoxItems, bạn sẽ cần một cái gì đó như sau: (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.SelectedItemcó thể là null, trong khi Visual Studio tiếp tục nói với tôi rằng KeyValuePairkhông thể là null. Đó là lý do tại sao tôi SelectedItemchuyển thành nullable KeyValuePair<string, string>?. Sau đó, tôi kiểm tra xem selectedItemcó giá trị nào khác không null. Cách tiếp cận này có thể áp dụng cho bất kỳ loại mặt hàng nào bạn đã chọn.


0

Nếu bạn thực sự cần SelectionChangedsự kiện, thì câu trả lời tốt nhất là câu trả lời của SwDevMan81. Tuy nhiên, nếu bạn đang bắt đầu với WPF, thì bạn có thể muốn tìm hiểu cách thực hiện mọi thứ theo cách WPF, khác với những ngày Windows Forms cũ thường dựa vào các sự kiện như SelectionChanged, với WPF và mẫu ViewModel của Chế độ xem, bạn nên sử dụng các ràng buộc. Đây là một ví dụ về mã:

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

Việc sử dụng e.AddedItems[0] as kProjectwhere kProject là một lớp lưu giữ dữ liệu đã làm việc cho tôi vì nó được mặc định cho các Loại bỏ [0] trước khi tôi phân biệt rõ ràng điều này. Cảm ơn SwDevMan81 vì những thông tin ban đầu đã trả lời câu hỏi này cho tôi.


0

Đừng phức tạp hóa mọi thứ mà không có lý do. Sử dụng thuộc tính SelectedValue, bạn có thể dễ dàng nhận được giá trị ComboBox đã chọn như sau: YourComboBoxName.SelectedValue.ToString ().

Phía sau thuộc tính SelectedValue được định nghĩa là: SelectedValue {get; set;} điều này có nghĩa là bạn có thể sử dụng nó để lấy hoặc đặt giá trị của ComboBox.

Sử dụng SelectedItem không phải là một cách hiệu quả để nhận giá trị ComboBox vì nó yêu cầu rất nhiều phân nhánh.


0

Bạn có thể kiểm tra thuộc tính SelectedIndex hoặc SelectedValue hoặc SelectedItem trong sự kiện SelectionChanged của điều khiển Combobox.


-2

Điều này sẽ làm việc cho bạn ...

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

2
Bạn có thể giải thích làm thế nào điều này trả lời câu hỏi?
Nathan Tuggy

-3

Tôi đã giải quyết điều này bằng cách sử dụng sự kiện DropDownClosed vì điều này sẽ kích hoạt một chút sau khi giá trị được thay đổi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.