无法在动态按钮

时间:2017-05-22 18:06:18

标签: c# arrays winforms

我正在尝试访问我在创建新对象时创建的按钮内的数组,但是当我使用它时按钮超出数组边界(但是访问按钮外部的相同索引没有问题) )

相关代码(请参阅下面的类别和费用类别):

    public void updateExpensesLabels()
    {
        deleteExpensesLabels();
        for (int i = 0; i < categories.Length; i++)
        {
            if (categories[i] != null)
            {
                categories[i].test();
                addExpense.Click += (s, e) =>
                {
                    categories[i].createNewExpense(Convert.ToInt32(expenseAmount.Text), Convert.ToString(expenseName.Text));
                };
             }
         }
     }

请注意,类别[i]没有任何问题,并打印出应有的随机文本,但是当我将测试放在按钮内时,单击按钮时问题就会消失。

编辑:我使测试更加明显,这一次,代码的输出是&#34;对象在按钮之外不是空的&#34;因为索引超出数组

而粉碎
            if (categories[i] == null)
            {
                MessageBox.Show("Its null outside the button code");
            }
            else
            {
                MessageBox.Show("Its not null outside the button code");
            }
            addExpense.Click += (s, e) =>
            {
                if (categories[i] == null)
                {
                    MessageBox.Show("Its null inside the button code");
                }
                categories[i].test();
                categories[i].createNewExpense(Convert.ToInt32(expenseAmount.Text), Convert.ToString(expenseName.Text));
            };

编辑2: System.IndexOutOfRangeException是个例外 细节 -

System.IndexOutOfRangeException occurred
  HResult=0x80131508
  Message=האינדקס נמצא מחוץ לגבולות המערך.
  Source=Budget Managment Prog
  StackTrace:
   at Budget_Managment_Prog.Form1.<>c__DisplayClass21_0.<updateExpensesLabels>b__0(Object s, EventArgs e) in C:\Users\user\OneDrive\Budget Management Prog\Budget Managment Prog\Budget Managment Prog\Form1.cs:line 213
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at Budget_Managment_Prog.Program.Main() in C:\Users\user\OneDrive\Budget Management Prog\Budget Managment Prog\Budget Managment Prog\Program.cs:line 19

Forms1 -

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Budget_Managment_Prog
{
        /// <summary>
        /// Expenses Section
        /// </summary>
        Category[] categories = new Category[0];
        TabPage[] categoryTab = new TabPage[0];
        Label[] expenseLabel = new Label[0];
        private void addCategoryButton_Click(object sender, EventArgs e)
        {
            increaseCategories();
            categories[Category.categoryNum] = new Category(Category.categoryNum, newCategoryTextBox.Text);
            Category.categoryNum++;
            increaseTabs();
            updateExpensesLabels();
        }

        private void increaseTabs()
        {
            TabPage[] temp = new TabPage[categoryTab.Length + 1];
            for (int i = 0; i < categoryTab.Length; i++)
            {
                temp[i] = categoryTab[i];
            }
            categoryTab = temp;
        }

        private void increaseCategories()
        {
            Category[] temp = new Category[categories.Length + 1];
            for (int i = 0; i < categories.Length; i++)
            {
                temp[i] = categories[i];
            }
            categories = temp;
        }

        public void updateExpensesLabels()
        {
            deleteExpensesLabels();
            for (int i = 0; i < categories.Length; i++)
            {
                if (categories[i] != null)
                {

                    categoryTab[i] = new TabPage();
                    categoryTab[i].Text = categories[i].name;
                    categoryTabControl.Controls.Add(categoryTab[i]);
                    Label addExpenseLabel = new Label(); addExpenseLabel.Text = "New Expense Here?";
                    addExpenseLabel.AutoSize = true;
                    addExpenseLabel.Top = 10; addExpenseLabel.Left = 15; categoryTab[i].Controls.Add(addExpenseLabel);
                    Label nameLabel = new Label(); nameLabel.Text = "Name:";
                    nameLabel.AutoSize = true;
                    nameLabel.Top = 25; nameLabel.Left = 25; categoryTab[i].Controls.Add(nameLabel);
                    Label amountLabel = new Label(); amountLabel.Text = "Money:";
                    amountLabel.AutoSize = true;
                    amountLabel.Top = 25; amountLabel.Left = 250; categoryTab[i].Controls.Add(amountLabel);
                    TextBox expenseName = new TextBox(); expenseName.Top = 50; expenseName.Left = 25; categoryTab[i].Controls.Add(expenseName);
                    TextBox expenseAmount = new TextBox(); expenseAmount.Top = 50; expenseAmount.Left = 250; categoryTab[i].Controls.Add(expenseAmount);
                    categories[i].test();
                    Button addExpense = new Button();
                    addExpense.Click += (s, e) =>
                    {
                        categories[i].createNewExpense(Convert.ToInt32(expenseAmount.Text), Convert.ToString(expenseName.Text));
                    };
                    categoryTab[i].Controls.Add(addExpense);
                    int entries = 0;
                    int labelNum = 0;
                    for (int j = 0; j < categories[i].expenses.Length; j++)
                    {
                        expenseLabel[labelNum] = new Label();
                        expenseLabel[labelNum].Text = Convert.ToString(categories[i].expenses[labelNum].num);
                        expenseLabel[labelNum].Top = 80 + (30 * entries); expenseLabel[labelNum].Left = 25;
                        categoryTab[i].Controls.Add(expenseLabel[labelNum]);
                        increaseLabelArray();
                        labelNum++;


                    }
                }
            }
        }

        private void deleteExpensesLabels()
        {
            for (int i = 0; i< categoryTab.Length; i++)
            {
                categoryTabControl.Controls.Remove(categoryTab[i]);
            }
        }

        private void increaseLabelArray()
        {
            Label[] temp = new Label[expenseLabel.Length + 1];
            for (int i = 0; i < expenseLabel.Length; i++)
            {
                temp[i] = expenseLabel[i];
            }
            expenseLabel = temp;
        }
    }
}

类别 -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace Budget_Managment_Prog
{
    class Category
    {
        private int numOfExpenses = 0;
        public Expense[] expenses = new Expense[0];
        public static int categoryNum = 0;
        public string name;
        public Category(int num1, string name1)
        {
            categoryNum = num1;
            name = name1;
        }

        public void createNewExpense( int expense2, string name2)
        {

            increaseArray();
            expenses[numOfExpenses] = new Expense(numOfExpenses, expense2, name2);
            numOfExpenses ++;           


        }

        public void deleteExpense(int num)
        {
            if (num > expenses.Length || num < 1)
            {
                MessageBox.Show("Invalid Entry for deletion, make sure the number is not bigger than the biggest person or smaller than 1");
            }
            else
            {
                Expense[] temp = new Expense[expenses.Length - 1];
                for (int i = 0; i < expenses.Length; i++)
                {
                    if (expenses[i].num < num)
                    {
                        temp[i] = expenses[i];
                    }
                    if (expenses[i].num > num)
                    {
                        expenses[i].num--;
                        temp[i - 1] = expenses[i];
                    }
                }
                expenses = temp;
                numOfExpenses--;
            }
        }
        public void increaseArray()
        {
            Expense[] temp = new Expense[expenses.Length + 1];
            for (int i = 0; i < expenses.Length; i++)
            {
                temp[i] = expenses[i];
            }
            expenses = temp;

        }

        public void test()
        {
            MessageBox.Show("The Problem is in category or expense classes");
        }
    }
}

费用 -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Budget_Managment_Prog
{
    class Expense
    {
        public int num;
        public int expense;
        public string name;
        public Expense(int num1, int expense1, string name1)
        {
            num = num1;
            expense = expense1;
            name = name1;
        }
    }


}

1 个答案:

答案 0 :(得分:2)

已更新

我找到了你的问题。它在categories[i]中。如果您调试该程序,您会看到当您添加new Categoryi is 0 categories[i].test()button click将正常运行。但问题在于,loop's iteration总是在button click之后,换句话说i工作时equal to 1已经categories[i]而你的categories[i].test(); var number = i; Button addExpense = new Button(); addExpense.Click += (s, e) => { categories[number].createNewExpense(Convert.ToInt32(expenseAmount.Text), Convert.ToString(expenseName.Text)); }; 1}}将超出界限 如果您更改代码中添加按钮的部分,您将不再获得异常:

public Expense[] expenses = new Expense[0]; 

您已宣布

expenses[numOfExpenses] = new Expense(numOfExpenses, expense2, name2);

然后你正在尝试这样做

numOfExpenses

expenses超出length List<Expense>,因为它是您声明的空数组。

我建议您使用Expense[]代替expenses.Add(new Expense(numOfExpenses, expense2, name2)).,因此它不会受到您在初始化时提供的数量的限制,当您需要添加新的费用时,您将只是使用class Category { public List<Expense> expenses = new List<Expense>(); public static int categoryNum = 0; public string name; public Category(int num1, string name1) { categoryNum = num1; name = name1; } public void createNewExpense(int expense2, string name2) { expenses.Add(new Expense(expenses.Count, expense2, name2)); } public void deleteExpense(int num) { if (num > expenses.Count || num < 1) { MessageBox.Show("Invalid Entry for deletion, make sure the number is not bigger than the biggest person or smaller than 1"); } else { expenses.RemoveAt(num); } } public void test() { MessageBox.Show("The Problem is in category or expense classes"); } }

以下是如何做到这一点的示例

serviceModel.read(
  "/Users(1)", {
    success: function(userModel) {
      this.getView().setModel(userModel, "userAuthenticated");
    },

    error: function(error) {

    },

    context: this
  }
);