C# WinForms (.NET 3.5):第一次选择后 ComboBox returns 空引用

C# WinForms (.NET 3.5): ComboBox returns null reference after first selection

注意:这是一个普通的 WinForms 应用程序。没有 WPF 或 WCF 或其他任何东西。

大家好,我正在开发一个 WinForms (.NET 3.5) 应用程序,但遇到了一个问题。我正在尝试根据所选州获取城市(都在 2 个不同的 ComboBox-es 中 DropDownStyle 设置为 DropDownList)。

我已经使用 SelectedValue 属性 在 SelectedIndexChanged 事件处理程序中实现了这个逻辑。 DataSource 是从数据库方法返回的 DataTableSelectedValue returns 是 DataRowView.

的实例

在表单构造函数 中,我填充状态 ComboBox 并使用 SelectedIndex 属性 以编程方式设置默认状态选择;然后进入事件处理程序,正确执行,并填充该州的城市 ComboBox

现在,当我使用鼠标更改选定状态 post-construction 和 运行 时,问题就来了。这再次转到事件处理程序,但是 SelectedValue 属性 returns 是空引用 。请帮忙。我附上下面的代码。

private void comboFindState_SelectedIndexChanged(object sender, EventArgs e)
        {

            DataRowView selectedState;
            int selectedStateId;
            DataTable citiesTable;

            selectedState = comboFindState.SelectedValue as DataRowView;


            if (selectedState != null) //Is true the first time around when the event is
            //triggered due to programmatic change of the index.
            //Then null afterwards, on change via mouse click.
            {
                selectedStateId = Convert.ToInt32(selectedState.Row["State Code"]);
                citiesTable = DatabaseHelper.getStateCities(selectedStateId);

                comboFindCity.DataSource = citiesTable; //Same binding for state ComboBox
                //in the form's constructor;
                comboFindCity.DisplayMember = "City"; //only here it says "State",
                comboFindCity.ValueMember = "City Code";// and here it says "State Code".

                comboFindCity.SelectedIndex = 0; //Same thing in the form's constructor for
                //setting default selected index of state ComboBox.
            }
            else
            {
                //just populates an error TextBox saying 'No Cities Found'
            }
        }

请注意,所有这一切都发生在 ComboBox 州,该州已经有人居住。城市ComboBox连第二次都没有进入范围,所以数据库没有问题。

编辑: 仅供参考,我已经从 绝对开始 comboFindState 为 tcomboFindState 设置了 ValueMember 属性 =52=]。所以这不是它不起作用的原因。另请注意,它第一次运行正常,因此证明 ValueMember 设置正确。

只要正确使用DataSource,没有变通方法。
在设置 DataSource 之前,将 属性 ValueMember 设置为您用于获取城市的列名称

comboFindState.ValueMember = "State Code";
comboFindState.DisplayMember = "StateName"; //will be displayed in the combobox
comboFindState.DataSource = yourDataTableOfStates;

然后SelectedValue将return的值State Code作为整数类型(在Object类型中装箱)
null 如果 comboFindState.SelectedIndex = -1

private void comboFindState_SelectedIndexChanged(object sender, EventArgs e)
{
    if (comboFindState.SelectedValue != null)
    {
        int selectedStateId = (int)comboFindState.SelectedValue;
        DataTable citiesTable = DatabaseHelper.getStateCities(selectedStateId);

        //Your code after getting list of the cities
    }
}

另外
如果你将设置 ValueMember 那么你可以使用 SelectedValueChanged 事件

...关于评论...
如果 DataSource 为空,编译器如何知道 'State Code' 的含义?如果不同,请解释
编译器与这个问题无关。这发生在运行时 当您设置 ValueMemberDataSourcenull 之前 )。然后 ValueMember 的值将被保存并仅在您调用 SelectedValue.
时使用 如果无法从 DataSource 的 properties/columns 中找到 ValueMember,则整个选定对象将被 returned,以防 DataSourceDataTable DataRowView 将 returned

当您设置 ValueMemberDataSource 不是 nullafter)。
如果 DataSource 的类型中存在 properties/columns,则将检查 ValueMember 的新值。如果不存在,则 ArgumentException 将被抛出