2013-05-15 27 views
7

Tại sao đặt SelectedValue của một ComboBox thành null gây ra một ArgumentNullException?Tại sao thiết lập ComboBox.SelectedValue thành null gây ra một ArgumentNullException?

Ngoại lệ chỉ xảy ra nếu ComboBox thực sự là một phần của Biểu mẫu. Tôi có thể đặt SelectedValue cho tất cả các loại giá trị hoặc loại không hợp lý nhưng tôi không thể đặt thành null.

Không phải là SelectedValue không được là null. Thực tế, giá trị của nó là null tại thời điểm tôi đang cố gắng đặt giá trị đó thành null.

Trong mã thực sự của tôi, điều này không xảy ra trong hàm khởi tạo và tôi không đặt thiết lập nó thành null. Mã đang sử dụng biến số sẽ xảy ra là null. Tôi có thể sửa lỗi bằng cách kiểm tra biến không phải là null trước khi cố gắng đặt SelectedValue. Nhưng điều tôi không hiểu là lý do tại sao Tôi không thể đặt giá trị đó thành giá trị null.

Mã chỉnh sửa: DataSource bây giờ chứa một mục trong đó giá trị ValueMembers thực sự là null

using System.Collections.Generic; 
using System.Windows.Forms; 

public class Form1 : Form { 
    public Form1() { 
     var comboBox1 = new ComboBox(); 
     Controls.Add(comboBox1); 
     comboBox1.ValueMember = "Key"; 
     comboBox1.DisplayMember = "Value"; 
     comboBox1.DataSource = new List<Record> { 
      new Record {Key = "1", Value = "One"}, 
      new Record {Key = null, Value = "null"} 
     }; 
     comboBox1.SelectedItem = null;   // no problem 
     comboBox1.SelectedValue = "";   // no problem 
     comboBox1.SelectedValue = new object(); // no problem 
     comboBox1.SelectedValue = null;   // ArgumentNullException!! 
    } 
} 

public class Record { 
    public string Key { get; set; } 
    public string Value { get; set; } 
} 
+0

Bạn có mã được liên kết đến sự kiện SelectedIndexChanged hoặc một số sự kiện khác được kích hoạt bởi thay đổi giá trị hiện tại không? – Steve

+0

Xem câu hỏi này có thể giúp ích không. http://stackoverflow.com/questions/2864065/c-sharp-set-combo-item-with-selectedvalue/2864119 –

+0

@Steve: Không. Mã mẫu ở trên là một ví dụ làm việc hoàn chỉnh cho thấy ngoại lệ. – comecme

Trả lời

0

Có lẽ đó là bởi vì nếu tài sản ValueMember của SelectedValue là Không có gì, thì SelectedValue sẽ trả ToString() trên SelectedItem.

5

Kiểm tra việc thực hiện của tài sản trong Reflector nó trông như thế này:

public object SelectedValue 
{ 
    get 
    { 
     if ((this.SelectedIndex != -1) && (this.dataManager != null)) 
     { 
      object item = this.dataManager[this.SelectedIndex]; 
      return this.FilterItemOnProperty(item, this.valueMember.BindingField); 
     } 
     return null; 
    } 
    set 
    { 
     if (this.dataManager != null) 
     { 
      string bindingField = this.valueMember.BindingField; 
      if (string.IsNullOrEmpty(bindingField)) 
      { 
       throw new InvalidOperationException(SR.GetString("ListControlEmptyValueMemberInSettingSelectedValue")); 
      } 
      PropertyDescriptor property = this.dataManager.GetItemProperties().Find(bindingField, true); 
      int num = this.dataManager.Find(property, value, true); 
      this.SelectedIndex = num; 
     } 
    } 
} 

Vì vậy, điều này dường như xoay quanh this.dataManager không được null.

Nếu this.dataManager không phải là null, setter sẽ gọi Find() với key thiết lập để các giá trị mà bạn đang thiết SelectedValue tới:

internal int Find(PropertyDescriptor property, object key, bool keepIndex) 
{ 
    if (key == null) 
    { 
     throw new ArgumentNullException("key"); 
    } 
    if (((property != null) && (this.list is IBindingList)) && ((IBindingList) this.list).SupportsSearching) 
    { 
     return ((IBindingList) this.list).Find(property, key); 
    } 
    if (property != null) 
    { 
     for (int i = 0; i < this.list.Count; i++) 
     { 
      object obj2 = property.GetValue(this.list[i]); 
      if (key.Equals(obj2)) 
      { 
       return i; 
      } 
     } 
    } 
    return -1; 
} 

Mà sẽ ném một ngoại lệ nếu key là null.

Tôi đoán rằng dataManager chỉ được đặt thành không null khi ComboBox được chèn vào vùng chứa (ví dụ: Biểu mẫu), đó là lý do tại sao nó không phát ra khi không có trong vùng chứa.

(Trong thực tế, dataManager sẽ được thiết lập để không null khi bạn thiết lập Control.DataSource tài sản để không null.)

Tuy nhiên, điều này dường như không hoàn toàn đúng, bởi vì bạn báo cáo một NullReferenceException và điều này rõ ràng ném một số ArgumentNullException.

[EDIT] Nó thực sự là một ArgumentNullExeption; OP đã được cập nhật cho phù hợp.

+0

+1 để phân tích "găng tay cao su" nhanh chóng và kỹ lưỡng như trước đây. Tôi lưu ý rằng ngoại lệ được ném thực sự là 'ArgumentNullException' ... nhưng không lưu ý ban đầu rằng' khóa' là thông số vi phạm, rằng bản thân bộ đặt không phải là nguồn của ngoại lệ. Công việc mạnh mẽ. :} – J0e3gan

+1

Tôi xin lỗi, ngoại lệ được ném thực sự là ArgumentNullException. Tôi sẽ thay đổi bài viết của mình. – comecme

+1

Vì vậy, câu hỏi bây giờ trở thành lý do tại sao phương thức Find không chấp nhận 'null' làm giá trị' khóa' của nó. Nó * là * có thể tạo một 'Record' với một' khóa' của 'null' và thêm nó vào' DataSource'. Nhưng bạn sẽ không thể đặt 'SelectedValue' thành giá trị đó. – comecme

2

Tôi đoán rằng điều này có thể là một sự thiếu sót về những gì phải là ArgumentNullException thay vì một NullReferenceException (được đưa vào triển khai của trình thiết lập thuộc tính).

Mở nhanh chóng kiểm tra mã mà bạn cung cấp (cộng với một phương pháp Main với var form1 = new Form1()), tuy nhiên, tôi thấy rằng tôi không thực sự có được một NullReferenceException như bạn mô tả mà là một ArgumentNullException như tôi mong đợi Tôi nên.

Bạn có chắc chắn rằng bạn đã lưu ý loại ngoại lệ chính xác không?

UPDATE:

Như Matthew Watson mô tả, tham số chỉ định bởi các ArgumentNullException là, trên thực tế, key.

+1

Bạn nói đúng. Đã chỉnh sửa câu hỏi của tôi. – comecme

0

Trên button_click, mã này fonctionned và xóa ArgumentNullException:

if (comboBoxPays.SelectedValue == null) 
{ 
    id_pays = 0; 
} 
else 
    id_pays = int.Parse(comboBoxPays.SelectedValue.ToString()); 
0

Tôi biết đây là một câu hỏi cũ, nhưng tôi có những lỗi tương tự ngay bây giờ và tôi đã thấy rằng tôi không thể thiết lập SelectedValue = null nhưng tôi đã quản lý để đặt nó thành DBNull.Value

Các vấn đề liên quan