/// <summary>
        /// Handles the DoWorker event for the worker
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            lock (syncLock)
            {
                Dictionary<string, string> inputVariableList = ((GadgetParameters)e.Argument).InputVariableList;

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));

                AddFreqGridDelegate addGrid = new AddFreqGridDelegate(AddFreqGrid);
                SetGridTextDelegate setText = new SetGridTextDelegate(SetGridText);
                AddGridRowDelegate addRow = new AddGridRowDelegate(AddGridRow);
                SetGridBarDelegate setBar = new SetGridBarDelegate(SetGridBar);
                RenderFrequencyHeaderDelegate renderHeader = new RenderFrequencyHeaderDelegate(RenderFrequencyHeader);
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawOutputGridBorders);

                string freqVar = GadgetOptions.MainVariableName;
                string weightVar = GadgetOptions.WeightVariableName;
                string strataVar = string.Empty;
                bool showConfLimits = false;
                bool showCumulativePercent = false;
                bool includeMissing = GadgetOptions.ShouldIncludeMissing;

                if (inputVariableList.ContainsKey("stratavar"))
                {
                    strataVar = inputVariableList["stratavar"];
                }
                if (inputVariableList.ContainsKey("showconflimits"))
                {
                    if (inputVariableList["showconflimits"].Equals("true"))
                    {
                        showConfLimits = true;
                    }
                }
                if (inputVariableList.ContainsKey("showcumulativepercent"))
                {
                    if (inputVariableList["showcumulativepercent"].Equals("true"))
                    {
                        showCumulativePercent = true;
                    }
                }

                List<string> stratas = new List<string>();
                if (!string.IsNullOrEmpty(strataVar))
                {
                    stratas.Add(strataVar);
                }

                try
                {
                    Configuration config = dashboardHelper.Config;
                    string yesValue = config.Settings.RepresentationOfYes;
                    string noValue = config.Settings.RepresentationOfNo;

                    RequestUpdateStatusDelegate requestUpdateStatus = new RequestUpdateStatusDelegate(RequestUpdateStatusMessage);
                    CheckForCancellationDelegate checkForCancellation = new CheckForCancellationDelegate(IsCancelled);

                    GadgetOptions.GadgetStatusUpdate += new GadgetStatusUpdateHandler(requestUpdateStatus);
                    GadgetOptions.GadgetCheckForCancellation += new GadgetCheckForCancellationHandler(checkForCancellation);

                    if (this.DataFilters != null && this.DataFilters.Count > 0)
                    {
                        GadgetOptions.CustomFilter = this.DataFilters.GenerateDataFilterString(false);
                    }
                    else
                    {
                        GadgetOptions.CustomFilter = string.Empty;
                    }

                    Dictionary<DataTable, List<DescriptiveStatistics>> stratifiedFrequencyTables = dashboardHelper.GenerateFrequencyTable(GadgetOptions/*, freqVar, weightVar, stratas, string.Empty, useAllPossibleValues, sortHighLow, includeMissing, false*/);

                    if (stratifiedFrequencyTables == null || stratifiedFrequencyTables.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), DashboardSharedStrings.GADGET_MSG_NO_DATA);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), DashboardSharedStrings.GADGET_MSG_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;

                        foreach (KeyValuePair<DataTable, List<DescriptiveStatistics>> tableKvp in stratifiedFrequencyTables)
                        {
                            string strataValue = tableKvp.Key.TableName;

                            double count = 0;
                            foreach (DescriptiveStatistics ds in tableKvp.Value)
                            {
                                count = count + ds.observations;
                            }

                            if (count == 0 && stratifiedFrequencyTables.Count == 1)
                            {
                                // this is the only table and there are no records, so let the user know
                                this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), DashboardSharedStrings.GADGET_MSG_NO_DATA);
                                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                                return;
                            }
                            else if (count == 0)
                            {
                                continue;
                            }
                            DataTable frequencies = tableKvp.Key;

                            if (frequencies.Rows.Count == 0)
                            {
                                continue;
                            }

                            this.Dispatcher.BeginInvoke(addGrid, strataVar, frequencies.TableName);
                        }

                        foreach (KeyValuePair<DataTable, List<DescriptiveStatistics>> tableKvp in stratifiedFrequencyTables)
                        {
                            string strataValue = tableKvp.Key.TableName;

                            double count = 0;
                            foreach (DescriptiveStatistics ds in tableKvp.Value)
                            {
                                count = count + ds.observations;
                            }

                            if (count == 0)
                            {
                                continue;
                            }
                            DataTable frequencies = tableKvp.Key;

                            if (frequencies.Rows.Count == 0)
                            {
                                continue;
                            }

                            string tableHeading = tableKvp.Key.TableName;

                            if (stratifiedFrequencyTables.Count > 1)
                            {
                                tableHeading = freqVar;// +": " + strataVar + " = " + frequencies.TableName;
                            }

                            if (!showCumulativePercent)
                            {
                                this.Dispatcher.BeginInvoke(new SimpleCallback(HideCumulativePercent));
                            }

                            if (!showConfLimits)
                            {
                                this.Dispatcher.BeginInvoke(new SimpleCallback(HideConfidenceIntervals));
                            }

                            Field field = null;
                            string columnType = string.Empty;

                            foreach (DataRow fieldRow in dashboardHelper.FieldTable.Rows)
                            {
                                if (fieldRow["columnname"].Equals(freqVar))
                                {
                                    columnType = fieldRow["datatype"].ToString();
                                    if (fieldRow["epifieldtype"] is Field)
                                    {
                                        field = fieldRow["epifieldtype"] as Field;
                                    }
                                    break;
                                }
                            }

                            this.Dispatcher.BeginInvoke(renderHeader, strataValue, tableHeading);

                            double AccumulatedTotal = 0;
                            List<ConfLimit> confLimits = new List<ConfLimit>();
                            int rowCount = 1;
                            foreach (System.Data.DataRow row in frequencies.Rows)
                            {
                                if (!row[freqVar].Equals(DBNull.Value) || (row[freqVar].Equals(DBNull.Value) && includeMissing == true))
                                {
                                    this.Dispatcher.Invoke(addRow, strataValue, 26);
                                    string displayValue = row[freqVar].ToString();

                                    if (dashboardHelper.IsUserDefinedColumn(freqVar))
                                    {
                                        displayValue = dashboardHelper.GetFormattedOutput(freqVar, row[freqVar]);
                                    }
                                    else
                                    {
                                        if (field != null && field is YesNoField)
                                        {
                                            if (row[freqVar].ToString().Equals("1"))
                                                displayValue = yesValue;
                                            else if (row[freqVar].ToString().Equals("0"))
                                                displayValue = noValue;
                                        }
                                        else if ((field != null && field is DateField) || (!dashboardHelper.DateColumnRequiresTime(frequencies, frequencies.Columns[0].ColumnName)))
                                        {
                                            displayValue = string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:d}", row[freqVar]);
                                        }
                                        else if (field != null && field is TimeField)
                                        {
                                            displayValue = string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:T}", row[freqVar]);
                                        }
                                        else
                                        {
                                            displayValue = dashboardHelper.GetFormattedOutput(freqVar, row[freqVar]);
                                        }
                                    }

                                    if (string.IsNullOrEmpty(displayValue))
                                    {
                                        displayValue = config.Settings.RepresentationOfMissing;
                                    }

                                    double pct = 0;
                                    if (count > 0)
                                        pct = Convert.ToDouble(row["freq"]) / (count * 1.0);
                                    AccumulatedTotal += pct;

                                    if (count > 0)
                                        confLimits.Add(GetConfLimit(displayValue, Convert.ToDouble(row["freq"]), count));

                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Left, TextAlignment.Left, rowCount, 0, Visibility.Visible));
                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(row["freq"].ToString(), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 1, Visibility.Visible));

                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(pct.ToString("P"), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 2, Visibility.Visible));
                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(AccumulatedTotal.ToString("P"), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 3, Visibility.Visible));

                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(confLimits[rowCount - 1].Lower.ToString("P"), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 4, Visibility.Visible));
                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(confLimits[rowCount - 1].Upper.ToString("P"), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 5, Visibility.Visible));
                                    this.Dispatcher.BeginInvoke(setBar, strataValue, rowCount, pct);

                                    rowCount++;
                                }
                            }

                            this.Dispatcher.BeginInvoke(new AddGridFooterDelegate(RenderFrequencyFooter), strataValue, rowCount, (int)count);
                            this.Dispatcher.BeginInvoke(drawBorders, strataValue);
                        }

                        stratifiedFrequencyTables.Clear();
                    }
                    this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    stopwatch.Stop();
                    Debug.Print("Frequency gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
        /// <summary>
        /// Handles the DoWorker event for the worker
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            lock (syncLock)
            {
                Dictionary<string, string> inputVariableList = ((GadgetParameters)e.Argument).InputVariableList;

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));

                AddOutputGridDelegate addGrid = new AddOutputGridDelegate(AddLineListGrid);
                SetGridTextDelegate setText = new SetGridTextDelegate(SetGridText);
                SetGridImageDelegate setImage = new SetGridImageDelegate(SetGridImage);
                AddGridRowDelegate addRow = new AddGridRowDelegate(AddGridRow);
                RenderFrequencyHeaderDelegate renderHeader = new RenderFrequencyHeaderDelegate(RenderFrequencyHeader);
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawFrequencyBorders);

                Configuration config = DashboardHelper.Config;
                string yesValue = config.Settings.RepresentationOfYes;
                string noValue = config.Settings.RepresentationOfNo;

                string groupVar = string.Empty;
                int maxRows = 50;
                bool exceededMaxRows = false;
                bool exceededMaxColumns = false;
                bool showLineColumn = true;
                bool showColumnHeadings = true;
                bool showNullLabels = true;

                if (GadgetOptions.StrataVariableNames.Count > 0)
                {
                    groupVar = GadgetOptions.StrataVariableNames[0];
                }

                if (inputVariableList.ContainsKey("maxcolumns"))
                {
                    maxColumns = int.Parse(inputVariableList["maxcolumns"]);
                }

                if (inputVariableList.ContainsKey("maxrows"))
                {
                    maxRows = int.Parse(inputVariableList["maxrows"]);
                }

                if (inputVariableList.ContainsKey("showcolumnheadings"))
                {
                    showColumnHeadings = bool.Parse(inputVariableList["showcolumnheadings"]);
                }

                if (inputVariableList.ContainsKey("showlinecolumn"))
                {
                    showLineColumn = bool.Parse(inputVariableList["showlinecolumn"]);
                }

                if (inputVariableList.ContainsKey("shownulllabels"))
                {
                    showNullLabels = bool.Parse(inputVariableList["shownulllabels"]);
                }

                //System.Threading.Thread.Sleep(4000); // Artifically inflating process time to see how the 'loading' screen looks. TODO: REMOVE LATER

                if (IsHostedByEnter)
                {
                    if (System.Windows.SystemParameters.IsSlowMachine == true)
                    {
                        maxColumns = 512;
                    }
                    else
                    {
                        maxColumns = 1024;
                    }
                }
                else
                {
                    int renderingTier = (RenderCapability.Tier >> 16);
                    if (renderingTier >= 2)
                    {
                        maxColumns = 128;
                    }
                    else if (renderingTier >= 1)
                    {
                        maxColumns = 64;
                    }
                    else
                    {
                        maxColumns = 24;
                    }

                    if (System.Windows.SystemParameters.IsSlowMachine == true)
                    {
                        maxColumns = 24;
                    }
                }

                List<string> stratas = new List<string>();
                if (!string.IsNullOrEmpty(groupVar))
                {
                    stratas.Add(groupVar);
                }

                try
                {
                    GadgetOptions.GadgetStatusUpdate += new GadgetStatusUpdateHandler(requestUpdateStatus);
                    GadgetOptions.GadgetCheckForCancellation += new GadgetCheckForCancellationHandler(checkForCancellation);
                    if (this.DataFilters != null)
                    {
                        GadgetOptions.CustomFilter = this.DataFilters.GenerateDataFilterString(false);
                    }
                    else
                    {
                        GadgetOptions.CustomFilter = string.Empty;
                    }

                    List<DataTable> lineListTables = DashboardHelper.GenerateLineList(GadgetOptions);

                    if (lineListTables == null || lineListTables.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Line list thread cancelled");
                        return;
                    }
                    else if (lineListTables.Count == 1 && lineListTables[0].Rows.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Line list thread cancelled");
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Line list thread cancelled");
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;

                        foreach (DataTable listTable in lineListTables)
                        {
                            string strataValue = listTable.TableName;
                            if (listTable.Rows.Count == 0)
                            {
                                continue;
                            }
                            this.Dispatcher.BeginInvoke(addGrid, groupVar, listTable.TableName, listTable.Columns.Count);
                        }

                        SetGadgetStatusMessage(SharedStrings.DASHBOARD_GADGET_STATUS_DISPLAYING_OUTPUT);

                        foreach (DataTable listTable in lineListTables)
                        {
                            string strataValue = listTable.TableName;
                            if (listTable.Rows.Count == 0)
                            {
                                continue;
                            }
                            string tableHeading = listTable.TableName;

                            if (lineListTables.Count > 1)
                            {
                                //tableHeading = freqVar; ???
                            }

                            SetCustomColumnSort(listTable);

                            this.Dispatcher.BeginInvoke(renderHeader, strataValue, tableHeading, listTable.Columns);

                            rowCount = 1;

                            if (listTable.Columns.Count == 0)
                            {
                                throw new ApplicationException("There are no columns to display in this list. If specifying a group variable, ensure the group variable contains data fields.");
                            }

                            int[] totals = new int[listTable.Columns.Count - 1];
                            columnCount = 1;

                            foreach (System.Data.DataRow row in listTable.Rows)
                            {
                                this.Dispatcher.Invoke(addRow, strataValue, -1);
                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(rowCount.ToString(), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Stretch, TextAlignment.Center, rowCount, 0, Visibility.Visible), FontWeights.Normal);
                                columnCount = 1;

                                foreach (DataColumn column in listTable.Columns)
                                {
                                    if (columnCount > maxColumns + 1)
                                    {
                                        exceededMaxColumns = true;
                                        break;
                                    }

                                    string displayValue = row[column.ColumnName].ToString();

                                    if (DashboardHelper.IsUserDefinedColumn(column.ColumnName))
                                    {
                                        displayValue = DashboardHelper.GetFormattedOutput(column.ColumnName, row[column.ColumnName]);
                                    }
                                    else
                                    {
                                        Field field = null;
                                        string columnType = string.Empty;

                                        foreach (DataRow fieldRow in DashboardHelper.FieldTable.Rows)
                                        {
                                            if (fieldRow["columnname"].Equals(column.ColumnName))
                                            {
                                                columnType = fieldRow["datatype"].ToString();
                                                if (fieldRow["epifieldtype"] is Field)
                                                {
                                                    field = fieldRow["epifieldtype"] as Field;
                                                }
                                                break;
                                            }
                                        }

                                        if ((field != null && (field is YesNoField || field is CheckBoxField)) || column.DataType.ToString().Equals("System.Boolean"))
                                        {
                                            if (row[column.ColumnName].ToString().Equals("1") || row[column.ColumnName].ToString().ToLower().Equals("true"))
                                                displayValue = yesValue;
                                            else if (row[column.ColumnName].ToString().Equals("0") || row[column.ColumnName].ToString().ToLower().Equals("false"))
                                                displayValue = noValue;
                                        }
                                        else if ((field != null && field is DateField) || (!DashboardHelper.DateColumnRequiresTime(listTable, listTable.Columns[column.ColumnName].ColumnName)))
                                        {
                                            displayValue = string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:d}", row[column.ColumnName]);
                                        }
                                        else if (field != null && field is TimeField)
                                        {
                                            displayValue = string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:T}", row[column.ColumnName]);
                                        }
                                        else
                                        {
                                            displayValue = DashboardHelper.GetFormattedOutput(column.ColumnName, row[column.ColumnName]);
                                        }
                                    }

                                    if (string.IsNullOrEmpty(displayValue))
                                    {
                                        if (showNullLabels)
                                        {
                                            displayValue = config.Settings.RepresentationOfMissing;
                                        }
                                        else
                                        {
                                            displayValue = string.Empty;
                                        }
                                    }

                                    if (column.DataType.ToString().Equals("System.DateTime") || column.DataType.ToString().Equals("System.Int32") || column.DataType.ToString().Equals("System.Double") || column.DataType.ToString().Equals("System.Single"))
                                    {
                                        if (column.ColumnName.Equals("UniqueKey"))
                                        {
                                            this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(8, 6, 8, 6), VerticalAlignment.Stretch, HorizontalAlignment.Stretch, TextAlignment.Right, rowCount, columnCount, Visibility.Collapsed), FontWeights.Normal);
                                        }
                                        else
                                        {
                                            this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(8, 6, 8, 6), VerticalAlignment.Stretch, HorizontalAlignment.Stretch, TextAlignment.Right, rowCount, columnCount, Visibility.Visible), FontWeights.Normal);
                                        }
                                    }
                                    else if (column.DataType == typeof(byte[]) && displayValue != config.Settings.RepresentationOfMissing && IsHostedByEnter)
                                    {
                                        this.Dispatcher.BeginInvoke(setImage, strataValue, (byte[])row[column.ColumnName], new TextBlockConfig(displayValue, new Thickness(8, 6, 8, 6), VerticalAlignment.Stretch, HorizontalAlignment.Stretch, TextAlignment.Left, rowCount, columnCount, Visibility.Visible), FontWeights.Normal);
                                    }
                                    else
                                    {
                                        this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(8, 6, 8, 6), VerticalAlignment.Stretch, HorizontalAlignment.Stretch, TextAlignment.Left, rowCount, columnCount, Visibility.Visible), FontWeights.Normal);
                                    }
                                    columnCount++;
                                }

                                rowCount++;

                                if (rowCount > maxRows)
                                {
                                    break;
                                }
                            }

                            this.Dispatcher.BeginInvoke(drawBorders, strataValue);

                            if (rowCount > maxRows)
                            {
                                exceededMaxRows = true;
                            }
                        }

                        for(int i = 0; i < lineListTables.Count; i++)
                        {
                            lineListTables[i].Dispose();
                        }
                        lineListTables.Clear();
                    }

                    if (exceededMaxRows && exceededMaxColumns)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithWarningDelegate(RenderFinishWithWarning), "Warning: Some rows and columns were not displayed due to gadget settings. Showing top " + maxRows.ToString() + " rows and top " + maxColumns.ToString() + " columns only.");
                    }
                    else if (exceededMaxColumns)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithWarningDelegate(RenderFinishWithWarning), "Warning: Some columns were not displayed due to gadget settings. Showing top " + maxColumns.ToString() + " columns only.");
                    }
                    else if (exceededMaxRows)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithWarningDelegate(RenderFinishWithWarning), string.Format(SharedStrings.DASHBOARD_GADGET_STATUS_ROW_LIMIT, maxRows.ToString()));
                    }
                    else
                    {
                        this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                    }
                    // Now called after drawing all the borders.
                    // this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    stopwatch.Stop();
                    Debug.Print("Line list gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + DashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    Debug.Print(DashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
Example #3
0
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            lock (syncLock)
            {
                Dictionary<string, string> inputVariableList = ((GadgetParameters)e.Argument).InputVariableList;

                //Stopwatch stopwatch = new Stopwatch();
                //stopwatch.Start();

                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));

                AddFreqGridDelegate addGrid = new AddFreqGridDelegate(AddFreqGrid);
                SetGridTextDelegate setText = new SetGridTextDelegate(SetGridText);
                AddGridRowDelegate addRow = new AddGridRowDelegate(AddGridRow);
                RenderFrequencyHeaderDelegate renderHeader = new RenderFrequencyHeaderDelegate(RenderFrequencyHeader);
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawOutputGridBorders);

                string freqVar = string.Empty;
                string weightVar = string.Empty;
                string strataVar = string.Empty;
                string crosstabVar = string.Empty;
                bool includeMissing = false;
                bool outcomeContinuous = false;
                bool showStrataSummaryOnly = false;

                if (inputVariableList.ContainsKey("freqvar"))
                {
                    freqVar = inputVariableList["freqvar"];
                }

                if (inputVariableList.ContainsKey("crosstabvar"))
                {
                    crosstabVar = inputVariableList["crosstabvar"];
                }

                if (inputVariableList.ContainsKey("weightvar"))
                {
                    weightVar = inputVariableList["weightvar"];
                }

                if (inputVariableList.ContainsKey("stratavar"))
                {
                    strataVar = inputVariableList["stratavar"];
                }

                if (inputVariableList.ContainsKey("includemissing"))
                {
                    if (inputVariableList["includemissing"].Equals("true"))
                    {
                        includeMissing = true;
                    }
                }

                if (inputVariableList.ContainsKey("stratasummaryonly"))
                {
                    if (inputVariableList["stratasummaryonly"].Equals("true"))
                    {
                        showStrataSummaryOnly = true;
                    }
                }

                if (inputVariableList.ContainsKey("treatoutcomeascontinuous"))
                {
                    if (inputVariableList["treatoutcomeascontinuous"].Equals("true"))
                    {
                        outcomeContinuous = true;
                    }
                }

                List<string> stratas = new List<string>();
                if (!string.IsNullOrEmpty(strataVar))
                {
                    stratas.Add(strataVar);
                }

                try
                {
                    GadgetOptions.GadgetStatusUpdate += new GadgetStatusUpdateHandler(requestUpdateStatus);
                    GadgetOptions.GadgetCheckForCancellation += new GadgetCheckForCancellationHandler(checkForCancellation);

                    if (this.DataFilters != null && this.DataFilters.Count > 0)
                    {
                        GadgetOptions.CustomFilter = this.DataFilters.GenerateDataFilterString(false);
                    }
                    else
                    {
                        GadgetOptions.CustomFilter = string.Empty;
                    }

                    bool runGroup = false;

                    Dictionary<DataTable, List<DescriptiveStatistics>> stratifiedFrequencyTables = new Dictionary<DataTable, List<DescriptiveStatistics>>();

                    List<string> allGroupFields = DashboardHelper.GetAllGroupsAsList();

                    if (GadgetOptions.MainVariableNames != null && GadgetOptions.MainVariableNames.Count > 0)
                    {
                        Dictionary<DataTable, List<DescriptiveStatistics>> grpTables = new Dictionary<DataTable, List<DescriptiveStatistics>>();

                        foreach (string mainVariableName in GadgetOptions.MainVariableNames)
                        {
                            GadgetParameters newOptions = new GadgetParameters(GadgetOptions);
                            newOptions.MainVariableNames = null;
                            newOptions.MainVariableName = mainVariableName;

                            grpTables = DashboardHelper.GenerateFrequencyTable(newOptions);

                            foreach (KeyValuePair<DataTable, List<DescriptiveStatistics>> kvp in grpTables)
                            {
                                stratifiedFrequencyTables.Add(kvp.Key, kvp.Value);
                            }
                        }
                        runGroup = true;
                    }
                    else if (allGroupFields.Contains(GadgetOptions.MainVariableName))
                    {
                        Dictionary<DataTable, List<DescriptiveStatistics>> grpTables = new Dictionary<DataTable, List<DescriptiveStatistics>>();

                        foreach (string variableName in DashboardHelper.GetVariablesInGroup(GadgetOptions.MainVariableName))
                        {
                            if (!allGroupFields.Contains(variableName) && DashboardHelper.TableColumnNames.ContainsKey(variableName))
                            {
                                GadgetParameters newOptions = new GadgetParameters(GadgetOptions);
                                newOptions.MainVariableNames = null;
                                newOptions.MainVariableName = variableName;

                                grpTables = DashboardHelper.GenerateFrequencyTable(newOptions);

                                foreach (KeyValuePair<DataTable, List<DescriptiveStatistics>> kvp in grpTables)
                                {
                                    stratifiedFrequencyTables.Add(kvp.Key, kvp.Value);
                                }
                            }
                        }
                        runGroup = true;
                    }
                    else
                    {
                        stratifiedFrequencyTables = DashboardHelper.GenerateFrequencyTable(GadgetOptions/*, freqVar, weightVar, stratas, crosstabVar, useAllPossibleValues, sortHighLow, includeMissing, false*/);
                        runGroup = false;
                    }

                    if (runGroup) showStrataSummaryOnly = false;

                    if (stratifiedFrequencyTables == null || stratifiedFrequencyTables.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), DashboardSharedStrings.GADGET_MSG_NO_DATA);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        //Debug.Print("Thread cancelled");
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;

                        this.plusPlus = 0.0;
                        this.plusMinus = 0.0;
                        this.minusPlus = 0.0;
                        this.minusMinus = 0.0;
                        this.noCases = 0.0;
                        this.extraCases = 0.0;
                        this.noControls = 0.0;
                        this.extraControls = 0.0;

                        foreach (KeyValuePair<DataTable, List<DescriptiveStatistics>> tableKvp in stratifiedFrequencyTables)
                        {
                            SmartTable(tableKvp.Key);

                            string strataValue = tableKvp.Key.TableName;

                            double count = 0;
                            foreach (DescriptiveStatistics ds in tableKvp.Value)
                            {
                                count = count + ds.observations;
                            }

                            if (count == 0 && stratifiedFrequencyTables.Count == 1)
                            {
                                // this is the only table and there are no records, so let the user know
                                this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                                return;
                            }
                            else if (count == 0)
                            {
                                continue;
                            }
                            DataTable frequencies = tableKvp.Key;

                            if (YesValues.Count > 0 && NoValues.Count > 0)
                            {
                                frequencies = ApplyRowValueMappings(frequencies);
                                frequencies = ApplyColumnValueMappings(frequencies);
                            }

                            if (frequencies.Rows.Count == 0)
                            {
                                continue;
                            }

                            if (outcomeContinuous)
                            {
                                if (frequencies.Columns.Count <= 128)
                                {
                                    int min;
                                    int max;

                                    if (int.TryParse(frequencies.Columns[1].ColumnName, out min) && int.TryParse(frequencies.Columns[frequencies.Columns.Count - 1].ColumnName, out max))
                                    {
                                        bool addedColumns = false;

                                        for (int i = min; i <= max; i++)
                                        {
                                            if (!frequencies.Columns.Contains(i.ToString()))
                                            {
                                                DataColumn newColumn = new DataColumn(i.ToString(), typeof(double));
                                                newColumn.DefaultValue = 0;
                                                frequencies.Columns.Add(newColumn);
                                                addedColumns = true;
                                            }
                                        }

                                        if (addedColumns)
                                        {
                                            int ordinal = 1;
                                            for (int i = min; i <= max; i++)
                                            {
                                                if (frequencies.Columns.Contains(i.ToString()))
                                                {
                                                    frequencies.Columns[i.ToString()].SetOrdinal(ordinal);
                                                    ordinal++;
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            this.Dispatcher.BeginInvoke(addGrid, strataVar, frequencies.TableName, crosstabVar, frequencies.Columns[0].ToString(), frequencies);
                        }

                        foreach (KeyValuePair<DataTable, List<DescriptiveStatistics>> tableKvp in stratifiedFrequencyTables)
                        {
                            if (runGroup)
                            {
                                freqVar = tableKvp.Key.Columns[0].ColumnName;
                            }

                            string strataValue = tableKvp.Key.TableName;

                            double count = 0;
                            foreach (DescriptiveStatistics ds in tableKvp.Value)
                            {
                                count = count + ds.observations;
                            }

                            if (count == 0)
                            {
                                continue;
                            }
                            DataTable frequencies = tableKvp.Key;

                            if (YesValues.Count > 0 && NoValues.Count > 0)
                            {
                                frequencies = ApplyRowValueMappings(frequencies);
                                frequencies = ApplyColumnValueMappings(frequencies);
                            }

                            if (frequencies.Rows.Count == 0)
                            {
                                continue;
                            }

                            string tableHeading = tableKvp.Key.TableName;

                            if (stratifiedFrequencyTables.Count > 1)
                            {
                                tableHeading = freqVar;
                            }

                            this.Dispatcher.BeginInvoke(renderHeader, strataValue, tableHeading, frequencies.Columns);

                            rowCount = 1;

                            int[] totals = new int[frequencies.Columns.Count - 1];
                            columnCount = 1;

                            DataRow[] SortedRows = new DataRow[frequencies.Rows.Count];
                            int rowcounter = 0;
                            foreach (System.Data.DataRow row in frequencies.Rows)
                            {
                                SortedRows[rowcounter++] = row;
                                if (!row[freqVar].Equals(DBNull.Value) || (row[freqVar].Equals(DBNull.Value) && includeMissing == true))
                                {
                                    this.Dispatcher.Invoke(addRow, strataValue, -1);
                                    string displayValue = row[freqVar].ToString();

                                    if (DashboardHelper.IsUserDefinedColumn(freqVar))
                                    {
                                        displayValue = DashboardHelper.GetFormattedOutput(freqVar, row[freqVar]);
                                    }
                                    else
                                    {
                                        if (DashboardHelper.IsUsingEpiProject && View.Fields[freqVar] is YesNoField)
                                        {
                                            if (row[freqVar].ToString().Equals("1"))
                                                displayValue = "Yes";
                                            else if (row[freqVar].ToString().Equals("0"))
                                                displayValue = "No";
                                        }
                                        else if (DashboardHelper.IsUsingEpiProject && View.Fields[freqVar] is DateField)
                                        {
                                            displayValue = string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:d}", row[freqVar]);
                                        }
                                        else if (DashboardHelper.IsUsingEpiProject && View.Fields[freqVar] is TimeField)
                                        {
                                            displayValue = string.Format(System.Globalization.CultureInfo.CurrentCulture, "{0:T}", row[freqVar]);
                                        }
                                        else
                                        {
                                            displayValue = DashboardHelper.GetFormattedOutput(freqVar, row[freqVar]);
                                        }
                                    }

                                    if (string.IsNullOrEmpty(displayValue))
                                    {
                                        Configuration config = DashboardHelper.Config;
                                        displayValue = config.Settings.RepresentationOfMissing;
                                    }

                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Left, TextAlignment.Left, rowCount, 0, System.Windows.Visibility.Visible), FontWeights.Normal);

                                    int rowTotal = 0;
                                    columnCount = 1;

                                    foreach (DataColumn column in frequencies.Columns)
                                    {
                                        if (column.ColumnName.Equals(freqVar))
                                        {
                                            continue;
                                        }

                                        this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(row[column.ColumnName].ToString(), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, columnCount, System.Windows.Visibility.Visible), FontWeights.Normal);
                                        columnCount++;

                                        int rowValue = 0;
                                        bool success = int.TryParse(row[column.ColumnName].ToString(), out rowValue);
                                        if (success)
                                        {
                                            totals[columnCount - 2] = totals[columnCount - 2] + rowValue;
                                            rowTotal = rowTotal + rowValue;
                                        }
                                    }
                                    this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(rowTotal.ToString(), new Thickness(4, 0, 4, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, columnCount, System.Windows.Visibility.Visible), FontWeights.Bold);
                                    rowCount++;
                                }
                            }

                            double[] tableChiSq = Epi.Statistics.SingleMxN.CalcChiSq(SortedRows, false);
                            double tableChiSqDF = (double)(SortedRows.Length - 1) * (SortedRows[0].ItemArray.Length - 2);
                            double tableChiSqP = Epi.Statistics.SharedResources.PValFromChiSq(tableChiSq[0], tableChiSqDF);
                            String disclaimer = "";
                            if (tableChiSq[1] == 1.0)
                                disclaimer = SharedStrings.TABLES_CHI_SQUARE_NOT_VALID;

                            this.Dispatcher.BeginInvoke(new AddChiSquareDelegate(RenderChiSquare), tableChiSq[0], tableChiSqDF, tableChiSqP, disclaimer, strataValue);
                            this.Dispatcher.BeginInvoke(new AddGridFooterDelegate(RenderFrequencyFooter), strataValue, rowCount, totals);
                            this.Dispatcher.BeginInvoke(drawBorders, strataValue);
                        }
                    }

                    this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));

                    // check for existence of 2x2 table...
                    if (rowCount == 3 && columnCount == 3)
                    {
                    }

                    stratifiedFrequencyTables.Clear();
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    //stopwatch.Stop();
                    //Debug.Print("Crosstab gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    //Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            //Stopwatch stopwatch = new Stopwatch();
            //stopwatch.Start();
            Dictionary <string, string> inputVariableList = GadgetOptions.InputVariableList;

            lock (syncLock)
            {
                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));

                AddFreqGridDelegate           addGrid      = new AddFreqGridDelegate(AddFreqGrid);
                SetGridTextDelegate           setText      = new SetGridTextDelegate(SetGridText);
                AddGridRowDelegate            addRow       = new AddGridRowDelegate(AddGridRow);
                RenderFrequencyHeaderDelegate renderHeader = new RenderFrequencyHeaderDelegate(RenderFrequencyHeader);
                DrawFrequencyBordersDelegate  drawBorders  = new DrawFrequencyBordersDelegate(DrawOutputGridBorders);

                System.Collections.Generic.Dictionary <string, System.Data.DataTable> Freq_ListSet = new Dictionary <string, System.Data.DataTable>();

                string freqVar   = GadgetOptions.MainVariableName;
                string weightVar = GadgetOptions.WeightVariableName;
                string strataVar = string.Empty;

                if (GadgetOptions.StrataVariableNames != null && GadgetOptions.StrataVariableNames.Count > 0)
                {
                    strataVar = GadgetOptions.StrataVariableNames[0];
                }

                try
                {
                    List <string> stratas = new List <string>();
                    if (!string.IsNullOrEmpty(strataVar))
                    {
                        stratas.Add(strataVar);
                    }

                    DataTable dt             = new DataTable();
                    bool      booleanResults = false;
                    int       fields         = -1;

                    if (dashboardHelper.GetAllGroupsAsList().Contains(freqVar))
                    {
                        dt     = dashboardHelper.GenerateCombinedFrequencyTable(GadgetOptions, ref booleanResults);
                        fields = dashboardHelper.GetVariablesInGroup(freqVar).Count;
                    }
                    else
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), "Something that should never fail has failed.");
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }

                    if (dt == null || dt.Rows.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Combined frequency thread cancelled");
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;
                        double count        = Convert.ToDouble(dt.Compute("sum([count])", string.Empty)); //0;
                        this.Dispatcher.BeginInvoke(addGrid, strataVar, string.Empty);
                        string strataValue = dt.TableName;
                        this.Dispatcher.BeginInvoke(renderHeader, strataValue, freqVar);
                        //double AccumulatedTotal = 0;
                        int rowCount    = 1;
                        int denominator = dashboardHelper.RecordCount;

                        if (!booleanResults)
                        {
                            denominator = denominator * fields;
                        }

                        foreach (System.Data.DataRow row in dt.Rows)
                        {
                            if (!row["value"].Equals(DBNull.Value))
                            {
                                this.Dispatcher.Invoke(addRow, strataValue, 26);
                                string displayValue = row["value"].ToString();

                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(6, 0, 6, 0), VerticalAlignment.Center, HorizontalAlignment.Left, TextAlignment.Left, rowCount, 0, Visibility.Visible));
                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(row["count"].ToString(), new Thickness(6, 0, 6, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 1, Visibility.Visible));

                                double pct = 0;
                                if (count > 0)
                                {
                                    pct = Convert.ToDouble(row["count"]) / (double)denominator;
                                }
                                //AccumulatedTotal += pct;

                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(pct.ToString("P"), new Thickness(6, 0, 6, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 2, Visibility.Visible));

                                rowCount++;
                            }
                        }

                        this.Dispatcher.BeginInvoke(new AddGridFooterDelegate(RenderFrequencyFooter), strataValue, denominator, fields, booleanResults);
                        this.Dispatcher.BeginInvoke(drawBorders, strataValue);

                        this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                    }
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    //stopwatch.Stop();
                    //Debug.Print("Combined Frequency gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    //Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            lock (syncLock)
            {
                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawOutputGridBorders);
                AddDataGridDelegate          addDataGrid = new AddDataGridDelegate(AddDataGrid);

                System.Collections.Generic.Dictionary <string, System.Data.DataTable> Freq_ListSet = new Dictionary <string, System.Data.DataTable>();

                try
                {
                    DataTable dt             = new DataTable();
                    bool      booleanResults = false;
                    int       fields         = -1;

                    if (Parameters.ColumnNames.Count > 0)
                    {
                        //if (DashboardHelper.GetAllGroupsAsList().Contains(freqVar))
                        //{
                        dt = DashboardHelper.GenerateCombinedFrequencyTable(Parameters as CombinedFrequencyParameters, ref booleanResults, ref fields);
                        //fields = DashboardHelper.GetVariablesInGroup(freqVar).Count;
                        //}
                    }
                    else
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), "Something that should never fail has failed.");
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }

                    if (dt == null || dt.Rows.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Combined frequency thread cancelled");
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;
                        double count        = Convert.ToDouble(dt.Compute("sum([count])", string.Empty));
                        string strataValue  = dt.TableName;
                        int    denominator  = DashboardHelper.RecordCount;

                        if (!string.IsNullOrEmpty(Parameters.CustomFilter.Trim()))
                        {
                            denominator = DashboardHelper.DataSet.Tables[0].Select(Parameters.CustomFilter.Trim()).Count();
                        }

                        if (!booleanResults)
                        {
                            denominator = denominator * fields;
                        }

                        dt.Columns[0].ColumnName = DashboardSharedStrings.COL_HEADER_VALUE;
                        dt.Columns[1].ColumnName = DashboardSharedStrings.COL_HEADER_FREQUENCY;
                        dt.Columns.Add(new DataColumn(DashboardSharedStrings.COL_HEADER_PERCENT, typeof(double)));

                        foreach (System.Data.DataRow row in dt.Rows)
                        {
                            if (!row[DashboardSharedStrings.COL_HEADER_VALUE].Equals(DBNull.Value))
                            {
                                double pct = 0;
                                if (count > 0)
                                {
                                    pct = Convert.ToDouble(row[DashboardSharedStrings.COL_HEADER_FREQUENCY]) / (double)denominator;
                                    row[DashboardSharedStrings.COL_HEADER_PERCENT] = pct;
                                }
                            }
                        }

                        this.Dispatcher.BeginInvoke(addDataGrid, dt.AsDataView(), dt.TableName);
                        this.Dispatcher.BeginInvoke(new AddGridFooterDelegate(RenderFrequencyFooter), strataValue, denominator, fields, booleanResults);
                        //this.Dispatcher.BeginInvoke(drawBorders, strataValue);

                        this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                        //this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                    }
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    //this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    //stopwatch.Stop();
                    //Debug.Print("Combined Frequency gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    //Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            //Stopwatch stopwatch = new Stopwatch();
            //stopwatch.Start();
            Dictionary<string, string> inputVariableList = GadgetOptions.InputVariableList;

            lock (syncLock)
            {
                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));

                AddFreqGridDelegate addGrid = new AddFreqGridDelegate(AddFreqGrid);
                SetGridTextDelegate setText = new SetGridTextDelegate(SetGridText);
                AddGridRowDelegate addRow = new AddGridRowDelegate(AddGridRow);
                RenderFrequencyHeaderDelegate renderHeader = new RenderFrequencyHeaderDelegate(RenderFrequencyHeader);
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawOutputGridBorders);

                System.Collections.Generic.Dictionary<string, System.Data.DataTable> Freq_ListSet = new Dictionary<string, System.Data.DataTable>();

                string freqVar = GadgetOptions.MainVariableName;
                string weightVar = GadgetOptions.WeightVariableName;
                string strataVar = string.Empty;

                if (GadgetOptions.StrataVariableNames != null && GadgetOptions.StrataVariableNames.Count > 0)
                {
                    strataVar = GadgetOptions.StrataVariableNames[0];
                }

                try
                {
                    List<string> stratas = new List<string>();
                    if (!string.IsNullOrEmpty(strataVar))
                    {
                        stratas.Add(strataVar);
                    }

                    DataTable dt = new DataTable();
                    bool booleanResults = false;
                    int fields = -1;

                    if (dashboardHelper.GetAllGroupsAsList().Contains(freqVar))
                    {
                        dt = dashboardHelper.GenerateCombinedFrequencyTable(GadgetOptions, ref booleanResults);
                        fields = dashboardHelper.GetVariablesInGroup(freqVar).Count;
                    }
                    else
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), "Something that should never fail has failed.");
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }

                    if (dt == null || dt.Rows.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Combined frequency thread cancelled");
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;
                        double count = Convert.ToDouble(dt.Compute("sum([count])", string.Empty));  //0;
                        this.Dispatcher.BeginInvoke(addGrid, strataVar, string.Empty);
                        string strataValue = dt.TableName;
                        this.Dispatcher.BeginInvoke(renderHeader, strataValue, freqVar);
                        //double AccumulatedTotal = 0;
                        int rowCount = 1;
                        int denominator = dashboardHelper.RecordCount;

                        if (!booleanResults)
                        {
                            denominator = denominator * fields;
                        }

                        foreach (System.Data.DataRow row in dt.Rows)
                        {
                            if (!row["value"].Equals(DBNull.Value))
                            {
                                this.Dispatcher.Invoke(addRow, strataValue, 26);
                                string displayValue = row["value"].ToString();

                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(displayValue, new Thickness(6, 0, 6, 0), VerticalAlignment.Center, HorizontalAlignment.Left, TextAlignment.Left, rowCount, 0, Visibility.Visible));
                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(row["count"].ToString(), new Thickness(6, 0, 6, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 1, Visibility.Visible));

                                double pct = 0;
                                if (count > 0)
                                {
                                    pct = Convert.ToDouble(row["count"]) / (double)denominator;
                                }
                                //AccumulatedTotal += pct;

                                this.Dispatcher.BeginInvoke(setText, strataValue, new TextBlockConfig(pct.ToString("P"), new Thickness(6, 0, 6, 0), VerticalAlignment.Center, HorizontalAlignment.Right, TextAlignment.Right, rowCount, 2, Visibility.Visible));

                                rowCount++;
                            }
                        }

                        this.Dispatcher.BeginInvoke(new AddGridFooterDelegate(RenderFrequencyFooter), strataValue, denominator, fields, booleanResults);
                        this.Dispatcher.BeginInvoke(drawBorders, strataValue);

                        this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                    }
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    //stopwatch.Stop();
                    //Debug.Print("Combined Frequency gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    //Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
        protected override void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            lock (syncLock)
            {
                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawOutputGridBorders);
                AddDataGridDelegate addDataGrid = new AddDataGridDelegate(AddDataGrid);

                System.Collections.Generic.Dictionary<string, System.Data.DataTable> Freq_ListSet = new Dictionary<string, System.Data.DataTable>();

                try
                {
                    DataTable dt = new DataTable();
                    bool booleanResults = false;
                    int fields = -1;

                    if (Parameters.ColumnNames.Count > 0)
                    {
                        //if (DashboardHelper.GetAllGroupsAsList().Contains(freqVar))
                        //{
                        dt = DashboardHelper.GenerateCombinedFrequencyTable(Parameters as CombinedFrequencyParameters, ref booleanResults, ref fields);
                        //fields = DashboardHelper.GetVariablesInGroup(freqVar).Count;
                        //}
                    }
                    else
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), "Something that should never fail has failed.");
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }

                    if (dt == null || dt.Rows.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.NO_RECORDS_SELECTED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        return;
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Combined frequency thread cancelled");
                        return;
                    }
                    else
                    {
                        string formatString = string.Empty;
                        double count = Convert.ToDouble(dt.Compute("sum([count])", string.Empty));
                        string strataValue = dt.TableName;
                        int denominator = DashboardHelper.RecordCount;

                        if (!string.IsNullOrEmpty(Parameters.CustomFilter.Trim()))
                        {
                            denominator = DashboardHelper.DataSet.Tables[0].Select(Parameters.CustomFilter.Trim()).Count();
                        }

                        if (!booleanResults)
                        {
                            denominator = denominator * fields;
                        }

                        dt.Columns[0].ColumnName = DashboardSharedStrings.COL_HEADER_VALUE;
                        dt.Columns[1].ColumnName = DashboardSharedStrings.COL_HEADER_FREQUENCY;
                        dt.Columns.Add(new DataColumn(DashboardSharedStrings.COL_HEADER_PERCENT, typeof(double)));

                        foreach (System.Data.DataRow row in dt.Rows)
                        {
                            if (!row[DashboardSharedStrings.COL_HEADER_VALUE].Equals(DBNull.Value))
                            {
                                double pct = 0;
                                if (count > 0)
                                {
                                    pct = Convert.ToDouble(row[DashboardSharedStrings.COL_HEADER_FREQUENCY]) / (double)denominator;
                                    row[DashboardSharedStrings.COL_HEADER_PERCENT] = pct;
                                }
                            }
                        }

                        this.Dispatcher.BeginInvoke(addDataGrid, dt.AsDataView(), dt.TableName);
                        this.Dispatcher.BeginInvoke(new AddGridFooterDelegate(RenderFrequencyFooter), strataValue, denominator, fields, booleanResults);
                        //this.Dispatcher.BeginInvoke(drawBorders, strataValue);

                        this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                        //this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                    }
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    //this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    //stopwatch.Stop();
                    //Debug.Print("Combined Frequency gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    //Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }
        /// <summary>
        /// Handles the DoWorker event for the worker
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        private void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            lock (syncLock)
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToProcessingState));
                this.Dispatcher.BeginInvoke(new SimpleCallback(ClearResults));

                AddLineListGridDelegate addGrid = new AddLineListGridDelegate(AddLineListGrid);
                SetGridTextDelegate setText = new SetGridTextDelegate(SetGridText);
                SetGridImageDelegate setImage = new SetGridImageDelegate(SetGridImage);
                AddGridRowDelegate addRow = new AddGridRowDelegate(AddGridRow);
                RenderFrequencyHeaderDelegate renderHeader = new RenderFrequencyHeaderDelegate(RenderFrequencyHeader);
                DrawFrequencyBordersDelegate drawBorders = new DrawFrequencyBordersDelegate(DrawFrequencyBorders);

                Configuration config = dashboardHelper.Config;
                string yesValue = config.Settings.RepresentationOfYes;
                string noValue = config.Settings.RepresentationOfNo;

                try
                {
                    DataTable dictionaryTable = dashboardHelper.FieldTable.Copy();

                    foreach (KeyValuePair<string, string> kvp in dashboardHelper.TableColumnNames)
                    {
                        DataRow row = dictionaryTable.Rows.Find(kvp.Key);
                        if(row == null)
                        {
                            dictionaryTable.Rows.Add(kvp.Key, kvp.Value);
                        }
                    }

                    if (dashboardHelper.IsUsingEpiProject)
                    {
                        dictionaryTable.Columns.Add("Page", typeof(int));
                        dictionaryTable.Columns.Add("Tab", typeof(int));
                        dictionaryTable.Columns.Add("Prompt", typeof(string));
                        dictionaryTable.Columns.Add("Items", typeof(string));

                        foreach (DataRow fieldRow in dictionaryTable.Rows)
                        {
                            if (fieldRow["epifieldtype"] is RenderableField)
                            {
                                RenderableField renderableField = fieldRow["epifieldtype"] as RenderableField;
                                fieldRow["Page"] = renderableField.Page.Position + 1;
                                fieldRow["Tab"] = renderableField.TabIndex;
                                fieldRow["Prompt"] = renderableField.PromptText;
                                if (renderableField is GroupField)
                                {
                                    GroupField groupField = renderableField as GroupField;
                                    fieldRow["Items"] = groupField.ChildFieldNames;
                                }
                                else if (renderableField is OptionField)
                                {
                                    OptionField optionField = renderableField as OptionField;
                                    fieldRow["Items"] = optionField.GetOptionsString();
                                }
                            }
                        }

                        dictionaryTable.Columns["columnname"].SetOrdinal(0);
                        dictionaryTable.Columns["Prompt"].SetOrdinal(1);
                        dictionaryTable.Columns["formname"].SetOrdinal(2);
                        dictionaryTable.Columns["Page"].SetOrdinal(3);
                        dictionaryTable.Columns["Tab"].SetOrdinal(4);
                        dictionaryTable.Columns["datatype"].SetOrdinal(5);
                        dictionaryTable.Columns["epifieldtype"].SetOrdinal(6);
                        dictionaryTable.Columns["tablename"].SetOrdinal(7);
                        dictionaryTable.Columns["Items"].SetOrdinal(8);
                    }

                    if (dictionaryTable == null || dictionaryTable.Rows.Count == 0)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), "There are no valid fields to display.");
                    }
                    else if (worker.CancellationPending)
                    {
                        this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), SharedStrings.DASHBOARD_GADGET_STATUS_OPERATION_CANCELLED);
                        this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                        Debug.Print("Data dictionary thread cancelled");
                        return;
                    }
                    else
                    {
                        this.Dispatcher.BeginInvoke(addGrid, "", "", dictionaryTable.Columns.Count);
                        string formatString = string.Empty;
                        this.Dispatcher.BeginInvoke(renderHeader, "", "", dictionaryTable.Columns);

                        int rowCount = 1;
                        int columnCount = 1;

                        foreach (System.Data.DataRow row in dictionaryTable.Rows)
                        {
                            bool isGroup = false;

                            this.Dispatcher.Invoke(addRow, "", 30);
                            this.Dispatcher.BeginInvoke(setText, "", new TextBlockConfig(StringLiterals.SPACE + rowCount.ToString() + StringLiterals.SPACE, new Thickness(2, 0, 2, 0), VerticalAlignment.Center, HorizontalAlignment.Center, rowCount, 0, Visibility.Visible), FontWeights.Normal);

                            columnCount = 1;
                            foreach (DataColumn column in dictionaryTable.Columns)
                            {
                                string displayValue = row[column.ColumnName].ToString();
                                if (column.ColumnName.Equals("epifieldtype"))
                                {
                                    displayValue = displayValue.Replace("Epi.Fields.", "");
                                    if (isGroup)
                                    {
                                        displayValue = "GroupField";
                                    }
                                }
                                else if (column.ColumnName.Equals("columnname"))
                                {
                                    isGroup = dashboardHelper.GetGroupFieldsAsList().Contains(displayValue);
                                }
                                this.Dispatcher.BeginInvoke(setText, "", new TextBlockConfig(displayValue, new Thickness(8, 8, 8, 8), VerticalAlignment.Center, HorizontalAlignment.Left, rowCount, columnCount, Visibility.Visible), FontWeights.Normal);
                                columnCount++;
                            }

                            rowCount++;
                        }

                        this.Dispatcher.BeginInvoke(drawBorders, "");
                    }

                    this.Dispatcher.BeginInvoke(new SimpleCallback(RenderFinish));
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                catch (Exception ex)
                {
                    this.Dispatcher.BeginInvoke(new RenderFinishWithErrorDelegate(RenderFinishWithError), ex.Message);
                    this.Dispatcher.BeginInvoke(new SimpleCallback(SetGadgetToFinishedState));
                }
                finally
                {
                    stopwatch.Stop();
                    Debug.Print("Data dictionary gadget took " + stopwatch.Elapsed.ToString() + " seconds to complete with " + dashboardHelper.RecordCount.ToString() + " records and the following filters:");
                    Debug.Print(dashboardHelper.DataFilters.GenerateDataFilterString());
                }
            }
        }