private void updateCellValue(Cell c, string name)
        {
            string content  = c.getContent();                       //get content of cell
            string preValue = c.getValue();                         //get current value of cell

            c.setPreValue(value);                                   //set previous value of cell to current value
            int           rowIndex    = getRowIndexByName(name);    //get row index of cell
            int           columnIndex = getColumnIndexByName(name); //get column index of cell
            List <string> list        = new List <string>();

            if (content != null && content != "")
            {
                expTree = new ExpTree(content.Substring(1));
                list    = expTree.parseVariables(content.Substring(1)); //get list of variables
                string n = getCellName(rowIndex, columnIndex);          //get name of current cell
                //addDependencies(n, list); //add to dependencies dictionary
                string val;
                foreach (string var in list)
                {
                    val = getCellByName(var).getValue();                  //get numerical value of cell
                    expTree.addToDictionary(var, val);                    //add variable name and value to expression tree dictionary
                }
                if (expTree.getDictionarySize() > 0)                      //variables exist in the tree
                {
                    expTree.resetTree(content.Substring(1));              //put variable values in tree
                }
                string value = expTree.Eval().ToString();                 //get value of expression and convert it to string
                spreadsheet[rowIndex, columnIndex].setValue(value, true); //set value of cell to new value
            }
            else
            {
                spreadsheet[rowIndex, columnIndex].setValue("", true);
            }
            rowChanged    = rowIndex;     //save the row number that was changed
            columnChanged = columnIndex;  //save the column number that was changed
            OnPropertyChanged("content"); //fire property changed event to update UI
        }
        private void CellPropertyChanged(object sender, PropertyChangedEventArgs e) //cell property changed event
        {
            int  rowIndex = 0, columnIndex = 0;
            bool found = false;

            //determine which cell threw the event
            for (int i = 0; i < rowCount; i++)
            {
                for (int j = 0; j < columnCount; j++)
                {
                    if (sender.Equals(spreadsheet[i, j])) //check if current cell is the one that sent the event
                    {
                        found       = true;
                        rowIndex    = i; //save row index of sender
                        columnIndex = j; //save column index of sender
                        break;           //break out of loop
                    }
                }
            }

            if ("content" == e.PropertyName)
            {
                if (found == true) //only proceed if sender was identified
                {
                    bool   error   = false;
                    string content = spreadsheet[rowIndex, columnIndex].getContent(); //get content string
                    if (content != null && content != "")
                    {
                        if (content.StartsWith("=")) //value needs to be updated
                        {
                            List <string> list = new List <string>();
                            expTree = new ExpTree(content.Substring(1));
                            list    = expTree.parseVariables(content.Substring(1));                 //get list of variables
                            if (checkVariablesExist(list))                                          //only execute following code if all variables exist in the spreadsheet
                            {
                                if (checkSelfReference(list, rowIndex, columnIndex))                //only execute following code if there aren't any self references in the formula
                                {
                                    visited.Add(getCell(rowIndex, columnIndex));                    //add starting cell to visited hash set
                                    string n = getCellName(rowIndex, columnIndex);                  //get name of current cell
                                    removeDependencies(n);                                          //remove old dependencies before adding new ones
                                    addDependencies(n, list);                                       //add to dependencies dictionary
                                    if (checkCircularReference(getCellName(rowIndex, columnIndex))) //only execute following code if there aren't any circular references in the formula
                                    {
                                        string val;
                                        foreach (string var in list)
                                        {
                                            val = getCellByName(var).getValue();                   //get numerical value of cell
                                            expTree.addToDictionary(var, val);                     //add variable name and value to expression tree dictionary
                                        }
                                        if (expTree.getDictionarySize() > 0)                       //variables exist in the tree
                                        {
                                            expTree.resetTree(content.Substring(1));               //put variable values in tree
                                        }
                                        string value = expTree.Eval().ToString();                  //get value of expression and convert it to string
                                        spreadsheet[rowIndex, columnIndex].setValue(value, false); //set value of cell to new value
                                    }
                                    else //expression in cell contained a circular reference
                                    {
                                        spreadsheet[rowIndex, columnIndex].setValue("!(circular reference)", false); //set value of cell to error message
                                        error = true;
                                        //visited.Clear(); //clear visited hash set for the next expression
                                    }
                                }
                                else //expression in cell contained a self reference
                                {
                                    spreadsheet[rowIndex, columnIndex].setValue("!(self reference)", false); //set value of cell to error message
                                    error = true;
                                }
                            }
                            else //expression in cell contained an invalid cell name
                            {
                                spreadsheet[rowIndex, columnIndex].setValue("!(bad reference)", false); //set value of cell to error message
                                error = true;
                            }
                        }
                        else //value is the same as content
                        {
                            string n = getCellName(rowIndex, columnIndex); //get cell name
                            removeDependencies(n);                                       //remove dependencies since cell is now just a constant value and doesn't reference any cells
                            spreadsheet[rowIndex, columnIndex].setValue(content, false); //set value of cell to content of cell
                        }
                    }
                    else
                    {
                        spreadsheet[rowIndex, columnIndex].setValue("", false);
                    }

                    bool   success = false;
                    string name    = getCellName(rowIndex, columnIndex); //get name of current cell
                    if (error == false)                                  //only update dependencies if there is not an error
                    {
                        //visited.Add(getCellByName(name)); //add starting cell to visited hash set
                        success = updateDependencies(name); //update dependencies of current cell, returns false if there is a circular dependency
                        //if(success == false) //there was a circular dependency in the expression
                        //{
                        //    spreadsheet[rowIndex, columnIndex].setValue("!(circular reference)", false); //set value of cell to error message
                        //    setPreValues(getCellByName(name)); //make sure values of dependent cells don't change
                        //}
                    }
                    visited.Clear();              //clear hash set for next expression
                    rowChanged    = rowIndex;     //save the row number that was changed
                    columnChanged = columnIndex;  //save the column number that was changed

                    OnPropertyChanged("content"); //fire PropertyChanged event
                }
            }
            else if ("value" == e.PropertyName)
            {
                rowChanged    = rowIndex;
                columnChanged = columnIndex;
                OnPropertyChanged("content"); //fire PropertyChanged event
            }

            else if ("BGColor" == e.PropertyName)
            {
                rowChanged    = rowIndex;
                columnChanged = columnIndex;
                OnPropertyChanged("BGColor"); //fire PropertyChanged event
            }
        }