选中项目时列表中的Datagrid崩溃 [英] Datagrid from list crashes when item selected

查看:41
本文介绍了选中项目时列表中的Datagrid崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

BindingList是正确的答案,它解决了所有问题,包括能够格式化列.这是我唯一需要更改的行,并且现在一切正常.

 //这在顶部:BindingList< Ingredient>selectedIngredients = new BindingList< Ingredient>();//这进入页面的Load方法:dgvRecipeIngredients.DataSource = new BindingSource(){DataSource = selectedIngredients};//这三个方法在从列表中添加或删除项目的方法中是适当的.//ResetBindings从列表中删除了项目,这在没有重置页面之前是没有发生的.selectedIngredients.Add(ingr);selectedIngredients.RemoveAt(idxSelectedIngr);selectedIngredients.ResetBindings(); 

我将所有内容都保留了下来,以便人们看到问题以及如何解决这些问题.

UI图片,其中一些数据位于第二个网格中(底部),并且准备添加成分我有一个gridview,可以将我的食材清单加入其中,效果很好.我有第二个gridvew,我希望能够从第一个gridview中添加成分.

 使用系统;使用System.Collections.Generic;使用System.ComponentModel;使用System.Data;使用System.Drawing;使用System.Linq;使用System.Text;使用System.Threading.Tasks;使用System.Windows.Forms;命名空间HealthierRecipes{公共局部类AddRecipe:表单{public static int ingrId = 0;public static int availIngrId = -1;私有静态int idxSelectedIngr = 0;私有静态int idxSelectedAvailIngr = -1;私有列表< Ingredient>selectedIngredients = new List< Ingredient>();公共AddRecipe(){InitializeComponent();}私人无效AddRecipe_Load(对象发送者,EventArgs e){使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){dgvAvailIngredients.DataSource = dbContext.Ingredients.OfType< Ingredient>().ToList();this.dgvRecipeIngredients.DataSource = selectedIngredients;formatPage();txtTotCals.Text ="0";txtTotCarbs.Text ="0";txtTotProtein.Text ="0";txtTotFat.Text ="0";}}私有void dgvRecipeIngredients_CellContentClick(对象发送者,DataGridViewCellEventArgs e){使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){idxSelectedIngr = e.RowIndex;ingrId = Convert.ToInt32(dgvRecipeIngredients.Rows [e.RowIndex] .Cells [0] .Value);//var ingr =(从dbContext.Ingredients中的r,其中r.IngredientId == ingrId选择r).First();//txtAddIngredient.Text = ingr.Name;//txtAddUnit.Text = ingr.Units;//txtAddAmount.Text = ingr.Amount.ToString();}}私有void dgvAvailIngredients_CellContentClick(对象发送者,DataGridViewCellEventArgs e){使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){idxSelectedAvailIngr = e.RowIndex;availIngrId = Convert.ToInt32(dgvAvailIngredients.Rows [e.RowIndex] .Cells [0] .Value);var ingr =(从dbContext.Ingredients中的r,其中r.IngredientId == availIngrId选择r).First();txtAddIngredient.Text = ingr.Name;txtAddUnit.Text = ingr.Units;txtAddAmount.Text = ingr.Amount.ToString();}}私人空白bnAddIngredient_Click(对象发送者,EventArgs e){使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){var ingr =(从dbContext.Ingredients中的r,其中r.IngredientId == availIngrId选择r).First();如果(availIngrId> 0){浮点数= 0;bool amountValid = float.TryParse(txtAddAmount.Text,超出amountNumber);如果(amountValid == false){MessageBox.Show(请仅在金额框中使用数字.");返回;}ingr.Amount = amountNumber;selectedIngredients.Add(ingr);txtAddIngredient.Text =";txtAddUnit.Text =";txtAddAmount.Text =";dgvRecipeIngredients.DataSource = null;dgvRecipeIngredients.DataSource = selectedIngredients;//TODO这是乘以数量的代码,然后将成分添加到配方中的地方.//包括更新配方营养.浮动成分=成分卡路里*成分数量;浮游原料=卡路里*含量*浮点数ingrpro =成分蛋白*成分量;float ingrfat = ingr.Fat * ingr.Amount;float totcals = float.Parse(txtTotCals.Text);float totcarbs = float.Parse(txtTotCarbs.Text);float totpro = float.Parse(txtTotProtein.Text);float totfat = float.Parse(txtTotFat.Text);txtTotCals.Text =(totcals + ingrcals).ToString();txtTotCarbs.Text =(totcarbs + ingrcarbs).ToString();txtTotProtein.Text =(totpro + ingrpro).ToString();txtTotFat.Text =(totfat + ingrfat).ToString();}else {MessageBox.Show(请选择要添加的成分.");}}}私人void bnSaveRecipe_Click_1(对象发送者,EventArgs e){//TODO保存配方使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){配方r =新的Recipe();如果(ValidateForm()){r.Name = txtRecName.Text;r.Dish = cbDish.SelectedItem.ToString();r.Servings = Int32.Parse(txtServings.Text);r.TotalCalories = Int32.Parse(txtTotCals.Text);r.TotalFat = Int32.Parse(txtTotFat.Text);r.TotalCarbs = Int32.Parse(txtTotCarbs.Text);r.TotalProtein = Int32.Parse(txtTotProtein.Text);r.Instructions = rtxtInstructions.Text;dbContext.Recipes.InsertOnSubmit(r);dbContext.SubmitChanges();MessageBox.Show(记录已保存",成功",MessageBoxButtons.OK,MessageBoxIcon.Information);int id = r.RecipeId;//r.IngredientList = selectedIngredients;IngredientList il = new IngredientList();foreach(选定的成分中的成分){il.RecipeId = id;il.IngredientId = ingr.IngredientId;il.IngredientAmount = ingr.Amount;}txtRecName.Text ="" ;;txtServings.Text =";txtTotCals.Text ="0";txtTotFat.Text ="0";txtTotCarbs.Text ="0";txtTotProtein.Text ="0";rtxtInstructions.Text =";dgvRecipeIngredients.DataSource = null;dgvRecipeIngredients.DataSource = selectedIngredients;}别的{MessageBox.Show(请在表单上的所有框中填写有效值.");}}}私人布尔ValidateForm(){bool输出= true;如果(txtRecName.Text.Length == 0){输出=假;}如果(cbDish.SelectedItem == null){输出=假;}int servesNumber = 0;布尔voservingsValid = int.TryParse(txtServings.Text,outingsNumber);如果(servingsValid == false){输出=假;}int卡路里数= 0;布尔卡路里数= int.TryParse(txtTotCals.Text,卡路里数);如果(caloriesValid == false){输出=假;}int fatNumber = 0;bool fatValid = int.TryParse(txtTotFat.Text,out fatNumber);如果(fatValid == false){输出=假;}int carbsNumber = 0;bool carbsValid = int.TryParse(txtTotCarbs.Text,掉出carbsNumber);如果(carbsValid == false){输出=假;}int proteinNumber = 0;bool proteinValid = int.TryParse(txtTotProtein.Text,outproteinNumber);如果(proteinValid ==假){输出=假;}返回输出;}私有无效btnAddCancel_Click(对象发送者,EventArgs e){//TODO从退出更改为取消Application.Exit();}私人空白bnDelIngr_Click(对象发送者,EventArgs e){//TODO-添加代码以删除已删除成分的营养信息-已完成,但尚未从列表中删除该项目.使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){var ingr =(从dbContext.Ingredients中的r,其中r.IngredientId == ingrId选择r).如果(ingrId> 0){浮动成分=成分卡路里*成分数量;浮游原料=卡路里*含量;浮点数ingrpro =成分蛋白*成分量;float ingrfat = ingr.Fat * ingr.Amount;float totcals = float.Parse(txtTotCals.Text);float totcarbs = float.Parse(txtTotCarbs.Text);float totpro = float.Parse(txtTotProtein.Text);float totfat = float.Parse(txtTotFat.Text);txtTotCals.Text =(totcals-ingrcals).ToString();txtTotCarbs.Text =(totcarbs-ingrcarbs).ToString();txtTotProtein.Text =(totpro-ingrpro).ToString();txtTotFat.Text =(totfat-ingrfat).ToString();ingr.Amount = 1;selectedIngredients.Remove(ingr);dgvRecipeIngredients.DataSource = null;dgvRecipeIngredients.DataSource = selectedIngredients;}else {MessageBox.Show(请选择要删除的成分.");}}}私人空白bnEdit_Click(对象发送者,EventArgs e){使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){//TODO-添加代码以删除已编辑成分的营养信息-已完成,但尚未从列表中删除该项目.var ingr =(从dbContext.Ingredients中的r,其中r.IngredientId == ingrId选择r).如果(ingrId> 0){txtAddIngredient.Text = ingr.Name;txtAddUnit.Text = ingr.Units;txtAddAmount.Text = ingr.Amount.ToString();浮动成分=成分卡路里*成分数量;浮游原料=卡路里*含量;浮点数ingrpro =成分蛋白*成分量;float ingrfat = ingr.Fat * ingr.Amount;float totcals = float.Parse(txtTotCals.Text);float totcarbs = float.Parse(txtTotCarbs.Text);float totpro = float.Parse(txtTotProtein.Text);float totfat = float.Parse(txtTotFat.Text);txtTotCals.Text =(totcals-ingrcals).ToString();txtTotCarbs.Text =(totcarbs-ingrcarbs).ToString();txtTotProtein.Text =(totpro-ingrpro).ToString();txtTotFat.Text =(totfat-ingrfat).ToString();selectedIngredients.Remove(ingr);dgvRecipeIngredients.DataSource = null;dgvRecipeIngredients.DataSource = selectedIngredients;}否则{MessageBox.Show(请选择要编辑的成分.");}}}私有无效formatPage(){dgvAvailIngredients.Columns [0] .Width = 25;dgvAvailIngredients.Columns [1] .Width = 150;dgvAvailIngredients.Columns [2] .Width = 75;dgvAvailIngredients.Columns [3] .Width = 25;dgvAvailIngredients.Columns [4] .Width = 50;dgvAvailIngredients.Columns [5] .Width = 50;dgvAvailIngredients.Columns [6] .Width = 50;dgvAvailIngredients.Columns [7] .Width = 50;dgvRecipeIngredients.Columns [0] .Width = 25;dgvRecipeIngredients.Columns [1] .Width = 150;dgvRecipeIngredients.Columns [2] .Width = 75;dgvRecipeIngredients.Columns [3] .Width = 25;dgvRecipeIngredients.Columns [4] .Width = 50;dgvRecipeIngredients.Columns [5] .Width = 50;dgvRecipeIngredients.Columns [6] .Width = 50;dgvRecipeIngredients.Columns [7] .Width = 50;}私有无效btnSearchIngr_Click(对象发送者,EventArgs e){字符串srch = txtSearchIngr.Text;使用(RecipeClassesDataContext dbContext = new RecipeClassesDataContext()){var ingrlist =从dbContext.Ingredients中的r开始,其中r.Name.Contains(srch)选择r;dgvAvailIngredients.DataSource = ingrlist;}}}} 

正在将成分从LINQ拉到SQL表.成分实际上是一个抽象类,具有HealthyIngredient和RegularIngredient子类,但两个子类都存储在同一SQL表中,其他子类具有其特定值的位置具有空值.

  CREATE TABLE [dbo].[Ingredient]([IngredientId] INT IDENTITY(1、1)非空,[Name] VARCHAR(50)NOT NULL,[单位] NCHAR(10)非空,[Amount] FLOAT DEFAULT((1))NOT NULL,[卡路里] INT NOT NULL,[Fat] INT NOT NULL,[Carbs] INT NOT NULL,[蛋白质] INT NOT NULL,[Discriminator] NVARCHAR(50)NOT NULL,[HealthyVariant1] NVARCHAR(50)NULL,[HealthyVariant2] NVARCHAR(50)NULL,[HealthyType] NVARCHAR(50)NULL,[RegularVariant] NVARCHAR(50)NULL,[HealthyVar1Id] INT NULL,[HealthyVar2Id] INT NULL,[RegVarId] INT NULL,聚集了主键([IngredientId] ASC) 

这似乎也很好用,包括一堆相当复杂的数学运算,包括将表的插入字段相乘并将它们添加到表单上其他位置的文本框中,并在第一个网格和第二个网格之间更改一些信息,因此数据全部正确地传递到第二个数据网格.

但是,如果我尝试从第二个数据网格中选择任何内容,则会收到一个错误,该错误使整个程序崩溃,并将其一直发送回Program.cs.

奇怪的是,每隔一段时间,如果我将datagrid设置为RowHeadderSelect并且仅单击行标题,它就可以正常工作,包括让我使用编辑按钮并再次正确地进行数学运算,然后它可以工作在该会话中,无论我单击哪里,都可以,但是当我重新启动程序时,它再次给我同样的错误.

我尝试使用List,IList,ICollection和IEnumerable,以防万一这是导致问题的我的列表类型,但事实并非如此.有人对我做错了什么建议吗?

我添加了更多相关代码.这是目前影响任何事物的仅有的三种方法-加载,添加,然后尝试单击datagridview.

我不知道将任何调试代码放在哪里,因为它在进入CellContentClick方法之前会崩溃.我在那里有一个断点,但它从未达到.我在想这是什么或如何加载数据,但是在页面上的datagrid中看起来都正确.是否应该以其他方式将数据设置到datagrid?感谢您的帮助.

  System.IndexOutOfRangeExceptionHResult = 0x80131508Message =索引-1没有值.源= System.Windows.Forms在System.Windows.Forms.CurrencyManager.get_Item(Int32索引)在System.Windows.Forms.CurrencyManager.get_Current()在System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnRowEnter(DataGridViewCellEventArgs e)在System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell,Int32 columnIndex,Int32 rowIndex,布尔值canCreateNewRow,布尔值验证失败发生)在System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex,Int32 rowIndex,布尔setAnchorCellAddress,布尔validateCurrentCell,布尔throughMouseClick)在System.Windows.Forms.DataGridView.OnRowHeaderMouseDown(HitTestInfo hti,布尔值isShiftDown,布尔值isControlDown)在System.Windows.Forms.DataGridView.OnCellMouseDown(DataGridViewCellMouseEventArgs e)在System.Windows.Forms.DataGridView.OnMouseDown(MouseEventArgs e)在System.Windows.Forms.Control.WmMouseDown处(Message& m,MouseButtons按钮,Int32单击)在System.Windows.Forms.Control.WndProc(Message& m)在System.Windows.Forms.DataGridView.WndProc(Message& m)在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)处在System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)处在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)在System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)在System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID,Int32原因,Int32 pvLoopData)在System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32原因,ApplicationContext上下文)在System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32原因,ApplicationContext上下文)在System.Windows.Forms.Application.Run(窗体mainForm)上在HealthierRecipes.Program.Main()中的C:\ Users \ Tania \ source \ repos \ Old \ HealthierRecipes \ HealthierRecipes \ Program.cs:第25行 

解决方案

经过多次测试,我将其分解,可以发布一个非常简单的示例来重现您所描述的内容.但是要笑...

在加载"表单事件中,有一行用于设置配方配料网格的数据源…

  this.dgvRecipeIngredients.DataSource = selectedIngredients; 


//注释掉那一行.


由于列表为空,因此我们此时无需设置网格数据源.单击添加按钮时,它将被设置.

请尝试一下,让我知道是否有帮助.

这似乎是另一个很好的示例,其中 BindingList< T> 是更好的选择.

BindingList was the correct answer, it fixed all of the problems, including being able to format the columns. Here are the only lines I had to change, and everything is working perfectly now.

//This went at the top:
BindingList<Ingredient> selectedIngredients = new BindingList<Ingredient>();

//This went in the page Load method:
dgvRecipeIngredients.DataSource = new BindingSource() { DataSource = selectedIngredients};

//These three went as appropriate in methods that added or removed items from the list. 
//The ResetBindings removed items from the list, which wasn’t happening before without resetting the page. 

selectedIngredients.Add(ingr);
selectedIngredients.RemoveAt(idxSelectedIngr);
selectedIngredients.ResetBindings();

I have left everything else as it was, so people can see the problems, and how this fixed them.

Picture of UI with some data in second grid (bottom) and an ingredient ready to be added I have one gridview that I am bringing my list of ingredients into that is working just fine. I have a second gridvew that I want to be able to add ingredients to from the first gridview.

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 HealthierRecipes
{
    public partial class AddRecipe : Form
    {
        public static int ingrId = 0;
        public static int availIngrId = -1;
        private static int idxSelectedIngr = 0;
        private static int idxSelectedAvailIngr = -1;
        private List<Ingredient> selectedIngredients = new List<Ingredient>();
        
        public AddRecipe()
        {
            InitializeComponent();
        }

        private void AddRecipe_Load(object sender, EventArgs e)
        {
            
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                dgvAvailIngredients.DataSource = dbContext.Ingredients.OfType<Ingredient>().ToList();
                this.dgvRecipeIngredients.DataSource = selectedIngredients;
                   
                formatPage();
                txtTotCals.Text = "0";
                txtTotCarbs.Text = "0";
                txtTotProtein.Text = "0";
                txtTotFat.Text = "0";   
            }    
        }

        private void dgvRecipeIngredients_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                idxSelectedIngr = e.RowIndex;
                ingrId = Convert.ToInt32(dgvRecipeIngredients.Rows[e.RowIndex].Cells[0].Value);

                //var ingr = (from r in dbContext.Ingredients where r.IngredientId == ingrId select r).First();
                //txtAddIngredient.Text = ingr.Name;
                //txtAddUnit.Text = ingr.Units;
                //txtAddAmount.Text = ingr.Amount.ToString();
            } 
        }

        private void dgvAvailIngredients_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                idxSelectedAvailIngr = e.RowIndex;
                availIngrId = Convert.ToInt32(dgvAvailIngredients.Rows[e.RowIndex].Cells[0].Value);

                var ingr = (from r in dbContext.Ingredients where r.IngredientId == availIngrId select r).First();
                txtAddIngredient.Text = ingr.Name;
                txtAddUnit.Text = ingr.Units;
                txtAddAmount.Text = ingr.Amount.ToString();
            }    
        }
        private void bnAddIngredient_Click(object sender, EventArgs e)
        {
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                var ingr = (from r in dbContext.Ingredients where r.IngredientId == availIngrId select r).First();

                if (availIngrId > 0)
                {
                    float amountNumber = 0;
                    bool amountValid = float.TryParse(txtAddAmount.Text, out amountNumber);
                    if (amountValid == false)
                    {
                        MessageBox.Show("Please only use numbers in the amount box.");
                        return;
                    }

                    ingr.Amount = amountNumber;
                    selectedIngredients.Add(ingr);
                    
                    txtAddIngredient.Text = "";
                    txtAddUnit.Text = "";
                    txtAddAmount.Text = "";

                    dgvRecipeIngredients.DataSource = null;
                    dgvRecipeIngredients.DataSource = selectedIngredients;


                    //TODO This is where the code to multiply the amount happens, then add the ingredient to the recipe. 
                    //Includes updating recipe nutrients.

                    float ingrcals = ingr.Calories * ingr.Amount;
                    float ingrcarbs = ingr.Calories * ingr.Amount;
                    float ingrpro = ingr.Protein * ingr.Amount;
                    float ingrfat = ingr.Fat * ingr.Amount;

                    float totcals = float.Parse(txtTotCals.Text);
                    float totcarbs = float.Parse(txtTotCarbs.Text);
                    float totpro = float.Parse(txtTotProtein.Text);
                    float totfat = float.Parse(txtTotFat.Text);

                    txtTotCals.Text = (totcals + ingrcals).ToString();
                    txtTotCarbs.Text = (totcarbs + ingrcarbs).ToString();
                    txtTotProtein.Text = (totpro + ingrpro).ToString();
                    txtTotFat.Text = (totfat + ingrfat).ToString();

                }
                else { MessageBox.Show("Please select an ingredient to add."); }

            }
        }


        private void bnSaveRecipe_Click_1(object sender, EventArgs e)
        {
            //TODO save recipe
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {

                Recipe r = new Recipe();

                if (ValidateForm())
                {
                    r.Name = txtRecName.Text;
                    r.Dish = cbDish.SelectedItem.ToString();
                    r.Servings = Int32.Parse(txtServings.Text);
                    r.TotalCalories = Int32.Parse(txtTotCals.Text);
                    r.TotalFat = Int32.Parse(txtTotFat.Text);
                    r.TotalCarbs = Int32.Parse(txtTotCarbs.Text);
                    r.TotalProtein = Int32.Parse(txtTotProtein.Text);
                    r.Instructions = rtxtInstructions.Text;

                    dbContext.Recipes.InsertOnSubmit(r);
                    dbContext.SubmitChanges();
                    MessageBox.Show("Record is saved", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    int id = r.RecipeId;

                    // r.IngredientList = selectedIngredients;

                    IngredientList il = new IngredientList();
                    foreach (Ingredient ingr in selectedIngredients)
                    {
                        il.RecipeId = id;
                        il.IngredientId = ingr.IngredientId;
                        il.IngredientAmount = ingr.Amount;
                    }


                    txtRecName.Text = "";
                    txtServings.Text = "";
                    txtTotCals.Text = "0";
                    txtTotFat.Text = "0";
                    txtTotCarbs.Text = "0";
                    txtTotProtein.Text = "0";
                    rtxtInstructions.Text = "";
                    dgvRecipeIngredients.DataSource = null;
                    dgvRecipeIngredients.DataSource = selectedIngredients;
                }
                else
                {
                    MessageBox.Show("Please fill in all boxes on form with valid values.");
                }
            }


        }

        private bool ValidateForm()
        {
            bool output = true;

            if (txtRecName.Text.Length == 0)
            {
                output = false;
            }

            if (cbDish.SelectedItem == null)
            {
                output = false;
            }


            int servingsNumber = 0;
            bool servingsValid = int.TryParse(txtServings.Text, out servingsNumber);
            if (servingsValid == false)
            {
                output = false;
            }

            int caloriesNumber = 0;
            bool caloriesValid = int.TryParse(txtTotCals.Text, out caloriesNumber);
            if (caloriesValid == false)
            {
                output = false;
            }

            int fatNumber = 0;
            bool fatValid = int.TryParse(txtTotFat.Text, out fatNumber);
            if (fatValid == false)
            {
                output = false;
            }

            int carbsNumber = 0;
            bool carbsValid = int.TryParse(txtTotCarbs.Text, out carbsNumber);
            if (carbsValid == false)
            {
                output = false;
            }

            int proteinNumber = 0;
            bool proteinValid = int.TryParse(txtTotProtein.Text, out proteinNumber);
            if (proteinValid == false)
            {
                output = false;
            }

            return output;
        }

        private void btnAddCancel_Click(object sender, EventArgs e)
        {
            //TODO Change from exit to cancel
            Application.Exit();
        }

        private void bnDelIngr_Click(object sender, EventArgs e)
        {
            //TODO - Add code to remove Nutrition info for removed ingredient - this is done, but it doesn't reomove the item from the list yet.

            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                var ingr = (from r in dbContext.Ingredients where r.IngredientId == ingrId select r).First();

                if (ingrId > 0)
                {

                    float ingrcals = ingr.Calories * ingr.Amount;
                    float ingrcarbs = ingr.Calories * ingr.Amount;
                    float ingrpro = ingr.Protein * ingr.Amount;
                    float ingrfat = ingr.Fat * ingr.Amount;

                    float totcals = float.Parse(txtTotCals.Text);
                    float totcarbs = float.Parse(txtTotCarbs.Text);
                    float totpro = float.Parse(txtTotProtein.Text);
                    float totfat = float.Parse(txtTotFat.Text);

                    txtTotCals.Text = (totcals - ingrcals).ToString();
                    txtTotCarbs.Text = (totcarbs - ingrcarbs).ToString();
                    txtTotProtein.Text = (totpro - ingrpro).ToString();
                    txtTotFat.Text = (totfat - ingrfat).ToString();

                    ingr.Amount = 1;
                    selectedIngredients.Remove(ingr);

                    dgvRecipeIngredients.DataSource = null;
                    dgvRecipeIngredients.DataSource = selectedIngredients;
                }
                else { MessageBox.Show("Please select an ingredient to delete."); }

            }
        }

        private void bnEdit_Click(object sender, EventArgs e)
        {
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                //TODO - Add code to remove Nutrition info for Edited ingredient - this is done, but it doesn't reomove the item from the list yet.
                var ingr = (from r in dbContext.Ingredients where r.IngredientId == ingrId select r).First();

                if (ingrId >0)
                {
                    txtAddIngredient.Text = ingr.Name;
                    txtAddUnit.Text = ingr.Units;
                    txtAddAmount.Text = ingr.Amount.ToString();

                    float ingrcals = ingr.Calories * ingr.Amount;
                    float ingrcarbs = ingr.Calories * ingr.Amount;
                    float ingrpro = ingr.Protein * ingr.Amount;
                    float ingrfat = ingr.Fat * ingr.Amount;

                    float totcals = float.Parse(txtTotCals.Text);
                    float totcarbs = float.Parse(txtTotCarbs.Text);
                    float totpro = float.Parse(txtTotProtein.Text);
                    float totfat = float.Parse(txtTotFat.Text);

                    txtTotCals.Text = (totcals - ingrcals).ToString();
                    txtTotCarbs.Text = (totcarbs - ingrcarbs).ToString();
                    txtTotProtein.Text = (totpro - ingrpro).ToString();
                    txtTotFat.Text = (totfat - ingrfat).ToString();
                    
                    selectedIngredients.Remove(ingr);

                    dgvRecipeIngredients.DataSource = null;
                    dgvRecipeIngredients.DataSource = selectedIngredients;
                }
                else { MessageBox.Show("Please select an ingredient to edit."); }
            }
                
        }

        private void formatPage()
        {
            dgvAvailIngredients.Columns[0].Width = 25;
            dgvAvailIngredients.Columns[1].Width = 150;
            dgvAvailIngredients.Columns[2].Width = 75;
            dgvAvailIngredients.Columns[3].Width = 25;
            dgvAvailIngredients.Columns[4].Width = 50;
            dgvAvailIngredients.Columns[5].Width = 50;
            dgvAvailIngredients.Columns[6].Width = 50;
            dgvAvailIngredients.Columns[7].Width = 50;

            dgvRecipeIngredients.Columns[0].Width = 25;
            dgvRecipeIngredients.Columns[1].Width = 150;
            dgvRecipeIngredients.Columns[2].Width = 75;
            dgvRecipeIngredients.Columns[3].Width = 25;
            dgvRecipeIngredients.Columns[4].Width = 50;
            dgvRecipeIngredients.Columns[5].Width = 50;
            dgvRecipeIngredients.Columns[6].Width = 50;
            dgvRecipeIngredients.Columns[7].Width = 50;

        }

        private void btnSearchIngr_Click(object sender, EventArgs e)
        {
            string srch = txtSearchIngr.Text;
            using (RecipeClassesDataContext dbContext = new RecipeClassesDataContext())
            {
                var ingrlist = from r in dbContext.Ingredients where r.Name.Contains(srch) select r;
                dgvAvailIngredients.DataSource = ingrlist;
            }
        }   
    }
}

Ingredient is being pulled from LINQ to SQL tables. Ingredient is actually an abstract class, with HealthyIngredient and RegularIngredient subclasses, but both subclasses are stored in the same SQL table, with null values in the places where the other subclass has its specific values.

CREATE TABLE [dbo].[Ingredient] (
[IngredientId]    INT           IDENTITY (1, 1) NOT NULL,
[Name]            VARCHAR (50)  NOT NULL,
[Units]           NCHAR (10)    NOT NULL,
[Amount]          FLOAT           DEFAULT ((1)) NOT NULL,
[Calories]        INT           NOT NULL,
[Fat]             INT           NOT NULL,
[Carbs]           INT           NOT NULL,
[Protein]         INT           NOT NULL,
[Discriminator]   NVARCHAR (50) NOT NULL,
[HealthyVariant1] NVARCHAR (50) NULL,
[HealthyVariant2] NVARCHAR (50) NULL,
[HealthyType]     NVARCHAR (50) NULL,
[RegularVariant]  NVARCHAR (50) NULL,
[HealthyVar1Id]   INT           NULL,
[HealthyVar2Id]   INT           NULL,
[RegVarId]        INT           NULL,
PRIMARY KEY CLUSTERED ([IngredientId] ASC)

This also seems to work just fine, including a bunch of fairly complicated math involving multiplying inserted fields of the table and adding them to text boxes elsewhere on the form, and changing some info between the first grid and the second, so the data is all being passed correctly to the second datagrid.

However, if I try to select anything from the second datagrid, I get an error that crashes the whole program and sends it all the way back to the Program.cs.

Strangely enough, every once in a while if I have the datagrid set to RowHeadderSelect and I only click on the row header, it works correctly, including letting me use the edit button and doing the math correctly again, and then it works during that session no matter where I click, but then when I restart the program it gives me the same error again.

I have tried List, IList, ICollection, and IEnumerable, just in case it was my list type causing the issue, but it doesn’t seem to be. Anyone have some suggestions about what I am doing wrong?

I have added more of the relevant code. These are the only three methods that affect anything at the moment - the Load, the Add, and then trying to click on the datagridview.

I don't know where to put any debugging code, since it crashes before it enters the CellContentClick method. I have a breakpoint there but it never reaches it. I am thinking that it is what or how I am loading the data, but it all looks right in the datagrid on the page. Is there a different way I should be setting up the data to the datagrid? Thanks for helping.

System.IndexOutOfRangeException
  HResult=0x80131508
  Message=Index -1 does not have a value.
  Source=System.Windows.Forms
   at System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
   at System.Windows.Forms.CurrencyManager.get_Current()
   at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnRowEnter(DataGridViewCellEventArgs e)
   at System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, Boolean canCreateNewRow, Boolean validationFailureOccurred)
   at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)
   at System.Windows.Forms.DataGridView.OnRowHeaderMouseDown(HitTestInfo hti, Boolean isShiftDown, Boolean isControlDown)
   at System.Windows.Forms.DataGridView.OnCellMouseDown(DataGridViewCellMouseEventArgs e)
   at System.Windows.Forms.DataGridView.OnMouseDown(MouseEventArgs e)
   at System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.DataGridView.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 HealthierRecipes.Program.Main() in C:\Users\Tania\source\repos\Old\HealthierRecipes\HealthierRecipes\Program.cs:line 25

解决方案

After quite a few tests, I broke this down and can post a very simple example to reproduce what you describe. But for grins...

In the forms "Load" event there is a line that sets the recipe ingredient grid’s data source…

this.dgvRecipeIngredients.DataSource = selectedIngredients;


// Comment out that line.


We do not need to set grids data source at this time since the list is empty. It will get set when the add button is clicked.

Please try this and let me know if this helps.

This looks like another good example where a BindingList<T> is a better choice.

这篇关于选中项目时列表中的Datagrid崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆