protected override void OnSaveButtonClick(EventArgs e)
        {
            dgvData.EndEdit();
            if (!this.Is_Validate())
            {
                MessageBox.Show("請先修正錯誤再儲存。");
                return;
            }

            this.Loading = true;
            string strHierarchyTitle = this.cboHierarchy.Text;
            int intDisplayOrder = int.Parse(this.nudDisplayOrder.Value.ToString());
            bool bRequired = this.chkRequired.Checked;
            bool bSelfAssessment = this.chkSelfAssessment.Checked;
            bool bCase = this.chkCase.Checked;
            bool bNoneCalculated = this.chkNoneCalculated.Checked;
            string strTitle = this.txtTitle.Text.Trim();
            List<UDT.QuestionOption> Qos = new List<UDT.QuestionOption>();
            foreach (DataGridViewRow row in this.dgvData.Rows)
            {
                if (row.IsNewRow)
                    continue;

                UDT.QuestionOption Qo = new UDT.QuestionOption();

                Qo.Title = (row.Cells[0].Value + "").Trim();
                Qo.DisplayOrder = int.Parse((row.Cells[1].Value + "").Trim());

                Qos.Add(Qo);
            }

            Task task = Task.Factory.StartNew(() =>
            {
                //  檢查題號與題目是否已存在?
                List<UDT.Question> oQuestions = Access.Select<UDT.Question>(string.Format("ref_survey_id ={0}", this.SurveyID));
                Dictionary<string, UDT.Question> dicQuestionIDs = new Dictionary<string, UDT.Question>();
                Dictionary<string, string> dicQuestionTitles = new Dictionary<string, string>();

                Dictionary<string, List<UDT.Question>> dicQHRelations = new Dictionary<string, List<UDT.Question>>();
                List<UDT.QHRelation> QHRelations = Access.Select<UDT.QHRelation>();
                List<string> aQs = new List<string>();

                oQuestions.ForEach((x) =>
                {
                    if (!dicQuestionIDs.ContainsKey(x.UID))
                        dicQuestionIDs.Add(x.UID, x);

                    if (!dicQuestionTitles.ContainsKey(x.UID))
                        dicQuestionTitles.Add(x.UID, x.Title.Trim().ToUpper());
                });

                dicQHRelations.Add(string.Empty, new List<UDT.Question>());
                foreach(UDT.QHRelation x in QHRelations)
                {
                    if (!dicQuestionIDs.ContainsKey(x.QuestionID.ToString()))
                        continue;

                    if (dicQuestionIDs[x.QuestionID.ToString()].SurveyID != this.SurveyID)
                        continue;

                    if (!dicQHRelations.ContainsKey(x.HierarchyTitle))
                        dicQHRelations.Add(x.HierarchyTitle, new List<UDT.Question>());

                    dicQHRelations[x.HierarchyTitle].Add(dicQuestionIDs[x.QuestionID.ToString()]);
                    aQs.Add(x.QuestionID.ToString());
                }

                oQuestions.ForEach((x) =>
                {
                    if (!aQs.Contains(x.UID))
                        dicQHRelations[string.Empty].Add(x);
                });
                List<UDT.Question> oQs = new List<UDT.Question>();
                if (dicQHRelations.ContainsKey(strHierarchyTitle))
                    oQs = dicQHRelations[strHierarchyTitle];
                if (this.Record.RecordStatus == FISCA.UDT.RecordStatus.Insert)
                {
                    if (oQs.Where(x => x.DisplayOrder == intDisplayOrder).Count() > 0)
                    {
                        throw new Exception("相同題號已存在。");
                    }
                }
                else
                {
                    if (oQs.Where(x => (x.DisplayOrder == intDisplayOrder && x.UID != this.Record.UID)).Count() > 0)
                    {
                        throw new Exception("相同題號已存在。");
                    }
                }
                if (this.Record.RecordStatus == FISCA.UDT.RecordStatus.Insert)
                {
                    if (oQuestions.Where(x=>x.Title.ToUpper() == strTitle.ToUpper()).Count() > 0)
                        throw new Exception("相同題目已存在。");
                }
                else
                {
                    if (oQuestions.Where(x=>(x.Title.ToUpper() == strTitle.ToUpper() && x.UID != this.Record.UID)).Count() > 0)
                        throw new Exception("相同題目已存在。");
                }

                this.Record.Title = strTitle;
                this.Record.Type = this.Type;
                this.Record.IsRequired = bRequired;
                this.Record.IsCase = bCase;
                this.Record.IsSelfAssessment = bSelfAssessment;
                this.Record.IsNoneCalculated = bNoneCalculated;
                this.Record.SurveyID = this.SurveyID;
                this.Record.DisplayOrder = intDisplayOrder;
                this.HierarchyTitle = strHierarchyTitle;

                this.Record.Save();

                List<UDT.QHRelation> nQHRelations = Access.Select<UDT.QHRelation>("ref_question_id=" + this.Record.UID);
                nQHRelations.ForEach(x => x.Deleted = true);
                nQHRelations.SaveAll();
                nQHRelations.Clear();
                if (!string.IsNullOrEmpty(strHierarchyTitle))
                {
                    UDT.QHRelation QHRelation = new UDT.QHRelation();

                    QHRelation.QuestionID = int.Parse(this.Record.UID);
                    QHRelation.HierarchyTitle = strHierarchyTitle;

                    nQHRelations.Add(QHRelation);
                }
                nQHRelations.SaveAll();
                List<UDT.QuestionOption> oQos = Access.Select<UDT.QuestionOption>("ref_question_id=" + this.Record.UID);
                oQos.ForEach(x => x.Deleted = true);
                oQos.SaveAll();
                foreach (UDT.QuestionOption QuestionOption in Qos)
                {
                    QuestionOption.QuestionID = int.Parse(this.Record.UID);
                }
                Qos.SaveAll();

                this.RecordDetails = Access.Select<UDT.QuestionOption>("ref_question_id=" + this.Record.UID);
            });
            task.ContinueWith((x) =>
            {
                if (x.Exception != null)
                {
                    MessageBox.Show(x.Exception.InnerException.Message);
                    this.Loading = false;
                    return;
                }

                this.Loading = false;
                this.DataBind();
            }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        }
        private void Save_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            try
            {
                string Err_Msg = string.Empty;

                string SurveyName = this.txtName.Text.Trim();

                if (string.IsNullOrEmpty(SurveyName))
                    Err_Msg += "請輸入評鑑樣版名稱。\n";

                if (!string.IsNullOrEmpty(Err_Msg))
                    throw new Exception(Err_Msg);

                //  所有的「評鑑樣版」
                List<UDT.Survey> Surveys = Access.Select<UDT.Survey>(string.Format(@"name='{0}'", SurveyName));
                //  若新增的「評鑑樣版」名稱已存在,則發出警告並跳出程式
                if ((this._Survey == null) && Surveys.Count() > 0)
                {
                    MessageBox.Show("同名之評鑑樣版已存在。");
                    this.DialogResult = System.Windows.Forms.DialogResult.None;
                    return;
                }
                //  若修改的「評鑑樣版」名稱已存在,且該「評鑑樣版」的「uid」非待修改「評鑑樣版」所擁有,則發出警告並跳出程式
                if ((this._Survey != null) && Surveys.Where(x => x.UID != this._Survey.UID).Count() > 0)
                {
                    MessageBox.Show("同名之評鑑樣版已存在。");
                    this.DialogResult = System.Windows.Forms.DialogResult.None;
                    return;
                }

                //  修改「問卷」
                if (this._Survey != null)
                {
                    this._Survey.Name = this.txtName.Text.Trim();
                    this._Survey.Category = this.txtCategory.Text.Trim();
                    this._Survey.Description = this.txtDescription.Text.Trim();
                    this._Survey.Save();
                    this.Close();
                    return;
                }

                //  待新增的「問卷」
                UDT.Survey nSurvey = new UDT.Survey();

                nSurvey.Name = SurveyName;
                nSurvey.Category = this.txtCategory.Text.Trim();
                nSurvey.Description = this.txtDescription.Text.Trim();

                nSurvey.Save();

                //  檢查是否複製「題目」
                ComboItem item = (ComboItem)this.cboSurvey.SelectedItem;
                if (item == null || item.Tag == null)
                {
                    //  不複製
                    this.Close();
                    return;
                }
                else
                {
                    //  複製「題目」、「答案選項」、及「題目標題」
                    string SurveyID = ((UDT.Survey)item.Tag).UID;
                    List<UDT.Question> oQuestions = Access.Select<UDT.Question>(string.Format(@"ref_survey_id = {0}", SurveyID));
                    List<UDT.Question> nQuestions = new List<UDT.Question>();
                    foreach (UDT.Question oQuestion in oQuestions)
                    {
                        UDT.Question nQuestion = new UDT.Question();

                        nQuestion.SurveyID = int.Parse(nSurvey.UID);
                        nQuestion.Title = oQuestion.Title;
                        nQuestion.Type = oQuestion.Type;
                        nQuestion.IsRequired = oQuestion.IsRequired;
                        nQuestion.IsCase = oQuestion.IsCase;
                        nQuestion.IsSelfAssessment = oQuestion.IsSelfAssessment;
                        nQuestion.DisplayOrder = oQuestion.DisplayOrder;

                        nQuestions.Add(nQuestion);
                    }
                    nQuestions.SaveAll();
                    nQuestions = Access.Select<UDT.Question>(string.Format(@"ref_survey_id = {0}", nSurvey.UID));
                    List<UDT.QuestionOption> oQuestionOptions = new List<UDT.QuestionOption>();
                    List<UDT.QuestionOption> nQuestionOptions = new List<UDT.QuestionOption>();
                    if (oQuestions.Count > 0)
                        oQuestionOptions = Access.Select<UDT.QuestionOption>(string.Format(@"ref_question_id in ({0})", string.Join(",", oQuestions.Select(x => x.UID))));
                    foreach (UDT.QuestionOption oQuestionOption in oQuestionOptions)
                    {
                        UDT.Question oQuestion = oQuestions.Where(x => x.UID == oQuestionOption.QuestionID.ToString()).ElementAt(0);
                        UDT.Question nQuestion = nQuestions.Where(x => x.Title == oQuestion.Title).ElementAt(0);

                        UDT.QuestionOption nQuestionOption = new UDT.QuestionOption();
                        nQuestionOption.QuestionID = int.Parse(nQuestion.UID);
                        nQuestionOption.Title = oQuestionOption.Title;
                        nQuestionOption.DisplayOrder = oQuestionOption.DisplayOrder;

                        nQuestionOptions.Add(nQuestionOption);
                    }
                    nQuestionOptions.SaveAll();
                    List<UDT.QHRelation> oQHRelations = new List<UDT.QHRelation>();
                    List<UDT.QHRelation> nQHRelations = new List<UDT.QHRelation>();
                    Dictionary<string, string> dicQHRelations = new Dictionary<string, string>();
                    if (oQuestions.Count > 0)
                        oQHRelations = Access.Select<UDT.QHRelation>(string.Format(@"ref_question_id in ({0})", string.Join(",", oQuestions.Select(x => x.UID))));
                    if (oQHRelations.Count > 0)
                    {
                        foreach(UDT.QHRelation QHRelation in oQHRelations)
                        {
                            if (!dicQHRelations.ContainsKey(QHRelation.QuestionID.ToString()))
                                dicQHRelations.Add(QHRelation.QuestionID.ToString(), QHRelation.HierarchyTitle);
                        }
                    }
                    foreach (UDT.QHRelation oQHRelation in oQHRelations)
                    {
                        UDT.Question oQuestion = oQuestions.Where(x => x.UID == oQHRelation.QuestionID.ToString()).ElementAt(0);
                        UDT.Question nQuestion = nQuestions.Where(x => x.Title == oQuestion.Title).ElementAt(0);

                        if (dicQHRelations.ContainsKey(oQuestion.UID))
                        {
                            UDT.QHRelation nQHRelation = new UDT.QHRelation();

                            nQHRelation.QuestionID = int.Parse(nQuestion.UID);
                            nQHRelation.HierarchyTitle = dicQHRelations[oQuestion.UID];

                            nQHRelations.Add(nQHRelation);
                        }
                    }
                    nQHRelations.SaveAll();
                    this.Close();
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                this.DialogResult = System.Windows.Forms.DialogResult.None;
            }
            finally
            {
                //this.Close();
            }
        }
        protected override void OnCopyButtonClick(EventArgs e)
        {
            PrivateControl.DetailContent detail_content = QuestionTemplate.TemplatePool.GetTemplate<SingleChoice>();

            //  複製題目
            detail_content.Record = new UDT.Question();
            //detail_content.Group = Guid.NewGuid().ToString();
            detail_content.PrimaryKey = this.SurveyID.ToString();
            detail_content.Type = this.Type;
            detail_content.DisplayOrder = null;
            detail_content.HierarchyTitle = this.cboHierarchy.Text;
            detail_content.HierarchyTitleSource = this.HierarchyTitleSource;
            detail_content.Record.SurveyID = this.SurveyID;
            detail_content.SurveyID = this.SurveyID;

            List<UDT.QuestionOption> Qos = new List<UDT.QuestionOption>();
            foreach (DataGridViewRow row in this.dgvData.Rows)
            {
                if (row.IsNewRow)
                    continue;

                UDT.QuestionOption QuestionOption = row.Tag as UDT.QuestionOption;

                if (QuestionOption == null)
                    QuestionOption = new UDT.QuestionOption();

                int display_order = 0;
                int.TryParse((row.Cells[1].Value + "").Trim(), out display_order);
                QuestionOption.DisplayOrder = display_order;
                QuestionOption.Title = (row.Cells[0].Value + "").Trim();

                Qos.Add(QuestionOption);
            }
            detail_content.RecordDetails = Qos;

            detail_content.Record.IsRequired = this.chkRequired.Checked;
            detail_content.Record.IsCase = this.chkCase.Checked;
            detail_content.Record.IsSelfAssessment = this.chkSelfAssessment.Checked;
            detail_content.Record.IsNoneCalculated = this.chkNoneCalculated.Checked;
            detail_content.Record.Title = string.Empty;

            Event.DeliverDetailContent.RaiseCopyDetailContentEvent(this, new Event.DeliverDetailContentEventArgs(detail_content));

            detail_content.DataBind();
        }