private void _multiRptItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            List <Model.IReport> newItems;

            if (e.NewItems != null)
            {
                newItems = e.NewItems.Cast <Model.IReport>().ToList();
            }
            else
            {
                newItems = new List <Model.IReport>();
            }

            List <Model.IReport> oldItems;

            if (e.OldItems != null)
            {
                oldItems = e.OldItems.Cast <Model.IReport>().ToList();
            }
            else
            {
                oldItems = new List <Model.IReport>();
            }
            MultiReportContent tmpContent;

            #region 針對動作修改對應的 _multivariateContent 內容
            switch (e.Action)
            {
            case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                for (int i = 0; i < newItems.Count; i++)
                {
                    Model.IReport rpt = newItems[i];
                    tmpContent = new MultiReportContent();
                    for (int j = 0; j < rpt.Contents.Count; j++)
                    {
                        Model.IRptOutput output = rpt.Contents[j];
                        switch (output.OType)
                        {
                        case Dashboard.Model.MtbOType.GRAPH:
                            tmpContent.Chart = Tool.BinaryToWPFImage(output.OutputInByteArr);
                            break;

                        case Dashboard.Model.MtbOType.TABLE:
                            tmpContent.DecomTable = Tool.BinaryToDataTable(output.OutputInByteArr);
                            if (tmpContent.DecomTable != null && tmpContent.DecomTable.Rows.Count > 0)
                            {
                                tmpContent.ShowTable = true;
                            }
                            else
                            {
                                tmpContent.ShowTable = false;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    tmpContent.Title   = rpt.Title;
                    tmpContent.RawData = rpt.RawData;
                    MultiVariateContent.Add(tmpContent);
                }

                break;

            case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                break;

            case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                MultiVariateContent.Clear();
                break;

            case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                for (int i = 0; i < newItems.Count; i++)
                {
                    Model.IReport rpt = newItems[i];
                    tmpContent = new MultiReportContent();
                    for (int j = 0; j < rpt.Contents.Count; j++)
                    {
                        Model.IRptOutput output = rpt.Contents[j];
                        switch (output.OType)
                        {
                        case Dashboard.Model.MtbOType.GRAPH:
                            tmpContent.Chart = Tool.BinaryToWPFImage(output.OutputInByteArr);
                            break;

                        case Dashboard.Model.MtbOType.TABLE:
                            tmpContent.DecomTable = Tool.BinaryToDataTable(output.OutputInByteArr);
                            if (tmpContent.DecomTable != null && tmpContent.DecomTable.Rows.Count > 0)
                            {
                                tmpContent.ShowTable = true;
                            }
                            else
                            {
                                tmpContent.ShowTable = false;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    tmpContent.Title   = rpt.Title;
                    tmpContent.RawData = rpt.RawData;
                    MultiVariateContent[e.OldStartingIndex + i] = tmpContent;
                }
                break;

            case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                List <MultiReportContent> tmpLst = new List <MultiReportContent>();
                for (int i = 0; i < newItems.Count; i++)
                {
                    Model.IReport rpt = newItems[i];
                    tmpContent = new MultiReportContent();
                    for (int j = 0; j < rpt.Contents.Count; j++)
                    {
                        Model.IRptOutput output = rpt.Contents[j];
                        switch (output.OType)
                        {
                        case Dashboard.Model.MtbOType.GRAPH:
                            tmpContent.Chart = Tool.BinaryToWPFImage(output.OutputInByteArr);
                            break;

                        case Dashboard.Model.MtbOType.TABLE:
                            tmpContent.DecomTable = Tool.BinaryToDataTable(output.OutputInByteArr);
                            if (tmpContent.DecomTable != null && tmpContent.DecomTable.Rows.Count > 0)
                            {
                                tmpContent.ShowTable = true;
                            }
                            else
                            {
                                tmpContent.ShowTable = false;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    tmpContent.Title   = rpt.Title;
                    tmpContent.RawData = rpt.RawData;
                    tmpLst.Add(tmpContent);
                }
                MultiVariateContent.Clear();
                MultiVariateContent = new ObservableCollection <MultiReportContent>(tmpLst);
                break;

            default:
                break;
            }
            #endregion
        }
        protected override void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            IsBusy = true;
            if (_spcItemInfoTable == null || _spcItemInfoTable.Rows.Count == 0)
            {
                return;
            }

            App.Current.Dispatcher.Invoke((Action) delegate // <--- HERE
            {
                _uniRptItems.Clear();
                _multiRptItems.Clear();
                _overviewItems.Clear();
                UnivariateContent.Clear();
                MultiVariateContent.Clear();
                OverviewTrend.Clear();
                ShowSeparator = false;
            });


            lock (_spcItemInfoTable)
            {
                string        connString = Database.DBQueryTool.GetConnString();
                StringBuilder query      = new StringBuilder();

                DataRow[]            spcItemRow = _spcItemInfoTable.Rows.Cast <DataRow>().ToArray();
                List <Model.IReport> rptItems   = new List <Model.IReport>();

                DataRow[] spcItemRow_uni = new DataRow[] { };
                DataRow[] spcItemRow_mul = new DataRow[] { };
                if (spcItemRow.Any(x => x.Field <string>("FLAG") == "T2"))
                {
                    spcItemRow_mul = spcItemRow.Where(x => x.Field <string>("FLAG") == "T2").ToArray();
                }
                if (spcItemRow.Any(x => x.Field <string>("FLAG") == "I"))
                {
                    spcItemRow_uni = spcItemRow.Where(x => x.Field <string>("FLAG") == "I").ToArray();
                }

                if (spcItemRow_mul.Length > 0 && spcItemRow_uni.Length > 0)
                {
                    ShowSeparator = true;
                }

                string start = string.Format("{0:yyyy-MM-dd} {1}", StartDate.Date, StartTimeValue);
                string end   = string.Format("{0:yyyy-MM-dd} {1}", EndDate.Date, EndTimeValue);

                string tmpDir = System.IO.Path.Combine(Environment.GetEnvironmentVariable("tmp"), "Minitab");
                try
                {
                    Array.ForEach(System.IO.Directory.GetFiles(tmpDir), System.IO.File.Delete); //刪除暫存區所有檔案
                }
                catch
                {
                }

                for (int i = 0; i < spcItemRow_mul.Length; i++)
                {
                    query.Clear();
                    Project.Commands.Delete();
                    Project.Worksheets.Delete();

                    DataRow dr = spcItemRow_mul[i];
                    Model.MultivariateReport rpt = new Model.MultivariateReport();
                    string[] item = dr["ITEM_LIST"].ToString().Split(',');
                    rpt.RawData = Database.DBQueryTool.GetPivotDataForMultivariateChart(_siteId, item, start, end);

                    //搜尋是否有參數
                    DataTable paraDetTable = null;
                    query.AppendLine("SELECT a.CHART_PARA_INDEX, b.FLAG, b.ROWNO, b.COLNO, b.VALUE, a.ITEM_LIST FROM CHART_PARAMETER a LEFT JOIN PARAMETER_DETAIL b");
                    query.AppendLine("ON a.CHART_PARA_INDEX = b.CHART_PARA_INDEX");
                    query.AppendFormat("WHERE a.ITEM_LIST='{0}'", dr["ITEM_LIST"].ToString());
                    paraDetTable   = Database.DBQueryTool.GetData(query.ToString(), Database.DBQueryTool.GetConnString());
                    rpt.Parameters = paraDetTable;

                    if (rpt.RawData != null && rpt.RawData.Rows.Count > 0)
                    {
                        rpt.Title = dr["TITLE"].ToString();
                        rpt.Flag  = dr["FLAG"].ToString();
                        try
                        {
                            rpt.Execute(_proj);
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Minitab run time error\r\n" + ex.Message);
                        }

                        rptItems.Add(rpt);
                        App.Current.Dispatcher.Invoke((Action) delegate // <--- HERE
                        {
                            _multiRptItems.Add(rpt);
                        });
                    }
                    if (_bgWorker.CancellationPending)
                    {
                        Console.WriteLine("**We need to cancel the work...call _bgWorker_RunWorkerCompleted**");
                        return;
                    }
                }

                /*
                 * 針對單變量取得時間內所有資料 (不用處理SPC的工作)
                 *
                 */
                int iCnt = 0;
                iCnt = _spcItemInfoTable.Select("FLAG='I'").Count();
                if (iCnt > 1)//超過1組資料才要畫整體趨勢圖
                {
                    string[] item = spcItemRow_uni.Select(x => x.Field <string>("ITEM_LIST")).ToArray();
                    Model.OverlayTrendReport rpt = new Model.OverlayTrendReport();
                    string sTime = string.Format("{0:yyyy-MM-dd hh:mm:ss}", start);
                    string eTime = string.Format("{0:yyyy-MM-dd hh:mm:ss}", end);
                    rpt.RawData = Database.DBQueryTool.GetPivotDataForMultivariateChart(SITE_ID, item, sTime, eTime);

                    if (rpt.RawData != null && rpt.RawData.Rows.Count > 0)
                    {
                        rpt.Title = "整體趨勢圖";
                        try
                        {
                            rpt.Execute(Project);
                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Minitab run time error\r\n" + ex.Message);
                        }
                        rptItems.Add(rpt);
                        App.Current.Dispatcher.Invoke((Action) delegate // <--- HERE
                        {
                            _overviewItems.Add(rpt);
                        });
                    }
                }


                for (int i = 0; i < spcItemRow_uni.Length; i++)
                {
                    query.Clear();
                    Project.Commands.Delete();
                    Project.Worksheets.Delete();
                    DataRow dr = spcItemRow_uni[i];
                    Model.UnivariateReport rpt = new Model.UnivariateReport();
                    string[] item = dr["ITEM_LIST"].ToString().Split(',');
                    item = item.Select(x => "'" + x + "'").ToArray();
                    query.Clear();
                    //query.AppendLine("SELECT * FROM VW_FURNACEDATAINSPC");
                    //query.AppendFormat("WHERE FURN_ITEM_INDEX IN ({0}) ", string.Join(",", item));
                    //query.AppendFormat("AND RPT_DATETIME BETWEEN '{0}' AND '{1}'\r\n", start, end);
                    //query.AppendLine("ORDER BY RPT_DATETIME");

                    query.AppendLine(Database.DBQueryTool.GetSQLString_FurnacedataInSPC(SITE_ID, item, start, end));
                    query.AppendLine("SELECT * FROM @tmpfurnacedatainspc order by rpt_datetime");
                    rpt.RawData = Database.DBQueryTool.GetData(query.ToString(), connString);

                    if (rpt.RawData != null && rpt.RawData.Rows.Count > 0)
                    {
                        rpt.Title = dr["TITLE"].ToString();
                        rpt.Flag  = dr["FLAG"].ToString();
                        rpt.Execute(_proj);
                        rptItems.Add(rpt);
                        App.Current.Dispatcher.Invoke((Action) delegate // <--- HERE
                        {
                            _uniRptItems.Add(rpt);
                        });
                    }
                    if (_bgWorker.CancellationPending)
                    {
                        Console.WriteLine("**We need to cancel the work...call _bgWorker_RunWorkerCompleted**");
                        return;
                    }
                }
            }
        }