在winforms / C#中更新组合框的Stackoverflow异常#

时间:2012-10-26 00:18:53

标签: c# winforms combobox stack-overflow

我正在考虑StackOverflowException。不知何故,在这里张贴似乎是合适的。

我在C#应用程序中使用Windows窗体。此应用程序旨在在Linux,FreeBSD和Mac-OS上运行,因此我无法使用WPF,因此请不要建议。

我的猜测是我错过了WinForms的细微差别,但我似乎无法弄清楚是什么。

ComboBox由VS 2010中的GUI表单构建器生成。

抛出错误的特定代码行在这里:

if(cur_num_is_valid)
{
    cbx_material_num.Text = num;
}
else
{
    num = "0";
    //I only have one of the following two at a time. Both overflow
    cbx_material_num.SelectedIndex = 0;
    cbx_material_num.Text = "0";
}

由于代码有点复杂,这里是整个功能代码。 'cbx_'表示一个组合框。 'txtb_'是一个文本框。

private void cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
{
    string obj = cbx_material_obj.Text;
    string num = cbx_material_num.Text;
    int selnum = 0;
    int n = 0;

    //do we need to recreate the numbers array?
    bool cur_num_is_valid = false;
    cbx_material_num.Items.Clear();
    if(obj != lastobj)
    {
        n = m_demo.get_object_modifiers(obj);
        for(int i = 0; i <= n; i++)
        {
            string s = i.ToString();
            if(s == num && i < n) cur_num_is_valid = true;
            cbx_material_num.Items.Add(s);
        }
    }
    if(cur_num_is_valid)
    {
        cbx_material_num.Text = num;
    }
    else
    {
        num = "0";
        //Overflow here:
        cbx_material_num.SelectedIndex = 0;
    }

    try
    {
        selnum = int.Parse(num);
    }
    catch(Exception)
    {
        MessageBox.Show("Error, second select menu after 'object modifiers' must be a number, not '"+num+"'.");
        cbx_material_num.Text="0";
        return;
    }

    if(selnum >= n)
    {
        txtb_material_param1.Text = "0";
        txtb_material_param2.Text = "0";
        txtb_material_param3.Text = "0";
        txtb_material_param4.Text = "0";
    }
    else
    {
        MaterialFace face;
        MaterialParameter parameter;
        int typeid;
        object paramdata;
        m_demo.get_object_modifiers_material(obj, selnum, out face, out parameter, out typeid, out paramdata);
        cbx_material_face.Text = face.ToString();
        cbx_material_paramtype.Text = parameter.ToString();
        switch(typeid)
        {
            case 0:
                txtb_material_param1.Text = ((float)paramdata).ToString();
                cbx_material_datatype.Text = "float";
                goto case -1;
            case 1:
                float[] parsf = ((float[])paramdata);
                txtb_material_param1.Text = parsf[0].ToString();
                txtb_material_param2.Text = parsf[1].ToString();
                txtb_material_param3.Text = parsf[2].ToString();
                txtb_material_param4.Text = parsf[3].ToString();
                cbx_material_datatype.Text = "float[]";
                break;
            case 2:
                txtb_material_param1.Text = ((int)paramdata).ToString();
                cbx_material_datatype.Text = "int";
                goto case -1;
            case 3:
                int[] parsi = ((int[])paramdata);
                txtb_material_param1.Text = parsi[0].ToString();
                txtb_material_param2.Text = parsi[1].ToString();
                txtb_material_param3.Text = parsi[2].ToString();
                txtb_material_param4.Text = parsi[3].ToString();
                cbx_material_datatype.Text = "int[]";
                break;
            case -1: //can't actuall be returned, used to 'blank' the last three as '0'
                txtb_material_param2.Text = "0";
                txtb_material_param2.Text = "0";
                txtb_material_param3.Text = "0";
                break;
            case 4:
                OpenTK.Graphics.Color4 paramc = ((OpenTK.Graphics.Color4)paramdata);
                txtb_material_param1.Text = paramc.R.ToString();
                txtb_material_param2.Text = paramc.G.ToString();
                txtb_material_param3.Text = paramc.B.ToString();
                txtb_material_param4.Text = paramc.A.ToString();
                cbx_material_datatype.Text = "Color4";
                break;
            default: //5
                Vector4 paramv = ((Vector4)paramdata);
                txtb_material_param1.Text = paramv.X.ToString();
                txtb_material_param2.Text = paramv.Y.ToString();
                txtb_material_param3.Text = paramv.Z.ToString();
                txtb_material_param4.Text = paramv.W.ToString();
                cbx_material_datatype.Text = "Vector4";
                break;
        }
    }
}

2 个答案:

答案 0 :(得分:2)

在尝试设置之前,您需要检查SelectedIndex是否已经为0:

    if (cbx_material_num.SelectedIndex != 0){
       cbx_material_num.SelectedIndex = 0;
    }

否则你每次都会重新开火。

答案 1 :(得分:0)

我认为无论何时在cbx_material_num.SelectedIndex = 0;内设置此EventHandler,您都会调用

cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)

每次调用都会调用另一个eventHandler,因此堆栈会在一段时间后填满。 基本上,它被称为SelectedIndexChanged的事实并不意味着该值必须与前一个值不同,而是通过其setter设置该值。