/// <summary>
        /// Refreshes the data in the gridview when a change is made to one of the view options
        /// </summary>
        /// <param name="sender">The sending object</param>
        /// <param name="e">The event arguments</param>
        private void OnUpdateData(object sender, EventArgs e)
        {
            // The process of initially setting up the view will trigger the event early.
            // This statement catches early triggers to prevent errors/needless computation
            if (view.Pivot.Text == null)
            {
                return;
            }

            var       store = Apsim.Find(table, typeof(IDataStore)) as IDataStore;
            DataTable input = store.Reader.GetData(view.Ledger.Text);

            // Don't try to update if data source isn't found
            if (input == null)
            {
                return;
            }

            // Find distinct values in the chosen pivot
            table.Pivots = new List <string>(
                input
                .AsEnumerable()
                .Select(r => r.Field <object>(view.Pivot.Text).ToString())
                .Distinct()
                .ToList());

            // Reset the table ID if the new pivot list is too short
            if (table.Pivots.Count <= table.ID)
            {
                table.ID = 0;
            }

            // Determine the row/column values
            var rows = input.AsEnumerable().Select(r => r.Field <object>(view.Row.Text)).Distinct();
            var cols = input.AsEnumerable().Select(r => r.Field <object>(view.Column.Text)).Distinct();

            DataTable output = new DataTable($"{view.Expression.Text}Of{table.GetPivot()}{view.Value.Text}");

            // Attach columns to the output table
            foreach (var col in cols)
            {
                output.Columns.Add(col.ToString(), typeof(double));
            }

            // Attach a column for the row titles
            string name = "Pivot: " + table.GetPivot();

            output.Columns.Add(name, typeof(string)).SetOrdinal(0);

            // Populate the table with rows
            foreach (var row in rows)
            {
                DataRow data = output.NewRow();
                data[name] = row;

                foreach (var col in cols)
                {
                    // Search DataTable for all values that match the current row/column
                    var items =
                        from item in input.AsEnumerable()
                        where item.Field <object>(view.Column.Text).ToString() == col.ToString()
                        where item.Field <object>(view.Row.Text).ToString() == row.ToString()
                        select item;

                    // Selects the values based on the current pivot
                    var values =
                        from item in items
                        where item.Field <object>(view.Pivot.Text).ToString() == table.GetPivot()
                        select item.Field <double>(view.Value.Text);

                    // Evaluate the expression on selected values
                    data[col.ToString()] = Aggregate(values);
                }
                output.Rows.Add(data);
                output.AcceptChanges();
            }

            view.gridview.DataSource = output;
        }