【问题标题】:Why does setting ComboBox.SelectedValue to null cause a ArgumentNullException?为什么将 ComboBox.SelectedValue 设置为 null 会导致 ArgumentNullException?
【发布时间】:2013-05-09 16:27:13
【问题描述】:

为什么将ComboBoxSelectedValue 设置为null 会导致ArgumentNullException

仅当 ComboBox 实际上是表单的一部分时才会发生异常。 我可以将SelectedValue 设置为各种没有意义的值或类型,但我不能将其设置为null

不是SelectedValue不能是null。事实上,在我尝试将其设置为 null 时,它的值 null

在我的真实代码中,这不会发生在构造函数中,我也没有明确地将其设置为null。该代码使用了一个恰好是null 的变量。我可以通过在尝试设置SelectedValue 之前检查变量不是null 来修复它。但我不明白的是为什么我不能将它设置为null 值。

代码编辑:DataSource 现在包含一个项目,其中 ValueMembers 值实际上是 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; }
}

【问题讨论】:

  • 您是否有代码链接到 SelectedIndexChanged 事件或由当前值更改触发的其他事件?
  • 看看这个问题是否有帮助。 stackoverflow.com/questions/2864065/…
  • @Steve:不。上面的示例代码是显示异常的完整工作示例。

标签: c# winforms combobox datasource nullreferenceexception


【解决方案1】:

检查Reflector中属性的实现看起来像这样:

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;
        }
    }
}

所以这似乎取决于this.dataManager 不为空。

如果this.dataManager 不为空,setter 将调用Find() 并将key 设置为您将SelectedValue 设置为的值:

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;
}

如果key 为空,会抛出异常。

我猜dataManager 仅在 ComboBox 插入容器(例如表单)时才设置为非 null,这就是它不在容器中时不会爆炸的原因。

(实际上,Control.DataSource 属性设置为非空时,dataManager 将设置为非空。)

但是,这似乎不太正确,因为您报告了 NullReferenceException,而这显然会抛出 ArgumentNullException

[编辑] 确实是ArgumentNullExeption; OP已相应更新。

【讨论】:

  • +1 进行快速彻底的“橡胶手套”分析。我注意到抛出的异常实际上是ArgumentNullException...但最初并没有注意到key 是有问题的参数,setter 本身不是异常的来源。强大的工作。 :}
  • 对不起,抛出的异常确实是ArgumentNullException。我会改变我的帖子。
  • 所以现在的问题变成了为什么 Find 方法不接受 null 作为其 key 值。 可以使用nullkey 创建一个Record 并将其添加到DataSource。但是您无法将 SelectedValue 设置为该值。
  • @comecme:为什么Find 不接受nullkey 的答案就在其正文的开头 - if (key == null) { throw new ArgumentNullException("key"); }
  • @J0e3gan 我明白了。这就是代码抛出异常的原因。但是为什么里面有那一行?我已经更新了我的代码,以表明拥有一个 DataMember 属性具有 null 值的项目是完全可以的。我希望能够将 SelectedValue 设置为 null,因为在这种情况下它是一个有效值。
【解决方案2】:

我的猜测是,这可能错过了应该是 ArgumentNullException 而不是 NullReferenceException(在属性设置器的实现中抛出)。

不过,在快速检查您提供的代码(加上带有var form1 = new Form1()Main 方法)时,我发现我实际上并没有像您描述的那样得到NullReferenceException,而是像我期望的那样得到ArgumentNullException应该。

您确定您记下的异常类型正确吗?

更新:

正如 Matthew Watson 所描述的,ArgumentNullException 指示的参数实际上是 key

【讨论】:

    【解决方案3】:

    可能是因为如果 SelectedValue 的 ValueMember 属性为 Nothing,那么 SelectedValue 会在 SelectedItem 上返回 .ToString()。

    【讨论】:

      【解决方案4】:

      在 button_click 上,这段代码被格式化并删除了 ArgumentNullException

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

      【讨论】:

        【解决方案5】:

        我知道这是一个老问题,但我现在有同样的错误,我发现我无法设置 SelectedValue = null 但我确实设法将它设置为 DBNull.Value

        【讨论】:

          猜你喜欢
          • 2014-11-06
          • 1970-01-01
          • 2015-01-28
          • 2016-10-23
          • 2012-08-22
          • 2012-08-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多