protected void Page_Load(object sender, EventArgs e)
        {
			//TODO: determine correct Permission
			//_Perm_Resource_Link_Ok = UserHasPermission(Permission.Hyperlink_Resource_Name);

			UserRole = Encryption.DecryptString(Request.QueryString["xID"].ToString());
			AssessmentCategory = Encryption.DecryptString(Request.QueryString["yID"].ToString());
			AssessmentID = (Request.QueryString["zID"] == null) ? "": Encryption.DecryptString(Request.QueryString["zID"].ToString());

			/************************************************************************************************
             * Security - Verify querystring parameters and user's roles are sufficient.
             ************************************************************************************************/

			Validate_Request();

			/************************************************************************************************
			 ************************************************************************************************
			 *							Initial Page Load.
			 ************************************************************************************************
			 ************************************************************************************************/
			var serializer = new JavaScriptSerializer();

			/************************************************************************************************
			 * Populate Class Properties and viewstate.
			 ************************************************************************************************/

			ImageWebFolder = (Request.ApplicationPath.Equals("/") ? string.Empty : Request.ApplicationPath) + "/Images/";

			districtParms = DistrictParms.LoadDistrictParms();

			//In this version of the app, are admins allowed to manage scheduling at the class level?
			AllowClassLevelSchedules = (districtParms.AssessmentSchedulerScheduleLevel == AssessmentScheduleLevels.Class.ToString());

			//In this version of the app, are admins allowed to set up scheduling for classroom assessments?
			AllowClassroomAssessmentScheduling = (districtParms.AssessmentSchedulerClassroomAssessments);

			//In this version of the app, are admins allowed to set up scheduling for proofed assessments, unproofed or both?
			IncludeUnproofedAssessments = (UserRole == "State") ?
												 districtParms.AssessmentSchedulerProofedOptionState :
												 districtParms.AssessmentSchedulerProofedOption; //Originally for Gwinnett

			//Load objects from viewstate if they are present, otherwise, pull from database.
			if (ViewState["ScheduleTypesList"] != null)
			{
				ScheduleTypesList = (List<Scheduling.ScheduleType>)ViewState["ScheduleTypesList"];
				ScheduleLevelsList = (List<Scheduling.ScheduleLevel>)ViewState["ScheduleLevelsList"]; ;
			}
			else
			{
				drGeneric_String_String AssessScheduleKeys = new drGeneric_String_String();
				var schedInstances = new List<Scheduling.Schedule>();
				var schedTypes = new List<Scheduling.ScheduleType>();
				var schedLevels = new List<Scheduling.ScheduleLevel>();

				Scheduling.GetScheduling(SessionObject.GlobalInputs,
										 ScheduleDocTypes.Assessment,
										 AssessmentScheduleLevels.District,
										 AssessScheduleKeys,
										 ref schedInstances,
										 ref schedTypes,
										 ref schedLevels);

				ScheduleTypesList = schedTypes;
				//Stash data from ScheduleTypesList in viewstate because we don't want to query for them again.
				ViewState["ScheduleTypesList"] = ScheduleTypesList;

				ScheduleLevelsList = schedLevels;

				//Stash key data from ScheduleLevelsList in viewstate because we don't want to query for them again.
				ViewState["ScheduleLevelsList"] = ScheduleLevelsList;
	
			}

			if (ViewState["SchedLevelForSave"] != null) SchedLevelForSave = (AssessmentScheduleLevels)ViewState["SchedLevelForSave"];

			if (!IsPostBack)
			{
				/************************************************************************************************
				 * Set up certain criteria controls with their selection values using Json arrays as datasources.
				 ************************************************************************************************/

				LoadCriteriaControls();

				/************************************************************************************************
				 * Reach up to the master page's RadAjaxPanel, and attach to it a javascript script to be 
				 * executed whenever the RadAjaxPanel's ajax call is executed.
				 ************************************************************************************************/
				RadAjaxPanel radAjaxPanel = (RadAjaxPanel)this.Master.FindControl("AjaxPanelResults");
				radAjaxPanel.ResponseScripts.Add("updateSelectedRowCount(0);");

				/************************************************************************************************
				 * If a AssessmentCategory was passed in, then set the Category combo box in the ScheduleCriteria control
				 * to this value and make it read only.
				 ************************************************************************************************/
				if (!string.IsNullOrEmpty(AssessmentCategory))
				{
					ctrlScheduleCriteria.DefaultCategory = AssessmentCategory;
					ctrlScheduleCriteria.CategoryReadOnly = true;
			}

			}

			if (radGridResults.DataSource == null)
            {
                radGridResults.Visible = false;
            }

            if (IsPostBack)
            {
				radGridResults.Visible = true;
			}

		}
        public void BindDataToGrid()
        {

            CriteriaController criteriaController = Master.CurrentCriteria();

            //
            // Reference Schedule criteria node and extract the selected values.
            //
            var scheduleCriteria_Category = "";
			scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.District;
            var scheduleCriteria = criteriaController.ParseCriteria<ScheduleCriteria.ValueObject>("ScheduleCriteria");
            if (scheduleCriteria.Count > 0) scheduleCriteria_Category = scheduleCriteria[0].Category;

			//
			// Reference District criteria node and extract the selected values.
			//
			var districts2_District = "";
			var districts2Criteria = criteriaController.ParseCriteria<E3Criteria.DropDownList.ValueObject>("Districts2");
			if (districts2Criteria.Count > 0) districts2_District = districts2Criteria[0].Value;

            //
            // Reference District criteria node and extract the selected values.
            //
            var Status_Status = "";
            var StatusStatus = criteriaController.ParseCriteria<E3Criteria.DropDownList.ValueObject>("Status");
            if (StatusStatus.Count > 0) Status_Status = StatusStatus[0].Value;

			//
            // Reference Curriculum criteria node and extract the selected values. 
            //
            var curriculum_Grade = "";
            var curriculum_Subject = "";
            var curriculum_Curriculum = "";
            var curriculum_Type = "";
            var curriculum_Term = "";
            var curriculumCriteria = criteriaController.ParseCriteria<Curriculum.ValueObject>("Curriculum");
			Thinkgate.Base.Classes.Course currCourseSelected;
			int curriculum_ID = 0;
            if (curriculumCriteria.Count > 0)
            {
                curriculum_Grade = curriculumCriteria[0].Grade;
                curriculum_Subject = curriculumCriteria[0].Subject;
                curriculum_Curriculum = curriculumCriteria[0].Curriculum;

				currCourseSelected = CourseMasterList.CurrCourseList.Find(x => 
																				x.Grade.DisplayText == (string.IsNullOrEmpty(curriculum_Grade) ? x.Grade.DisplayText: curriculum_Grade) 
																				&& 
																				x.Subject.DisplayText == (string.IsNullOrEmpty(curriculum_Subject) ? x.Subject.DisplayText : curriculum_Subject) 
																				&& 
																				x.CourseName == (string.IsNullOrEmpty(curriculum_Curriculum) ? x.CourseName : curriculum_Curriculum)
																		);
				//curriculum_ID = currCourseSelected.ID;                
                curriculum_Type = curriculumCriteria[0].Type;
                curriculum_Term = curriculumCriteria[0].Term;
            }

            //
            //  Reference Classes criteria node and extract the selected values.
            //
            var classes_Teacher = "";
            var classes_Semester = "";
            var classes_Period = "";
            var classes_Section = "";
            var classes_Block = "";
            var classesCriteria = criteriaController.ParseCriteria<E3Criteria.AssessmentSchedule.ClassesCriteria.ValueObject>("Classes");
            if (classesCriteria.Count > 0)
            {
                classes_Teacher = classesCriteria[0].Teacher;
                classes_Semester = classesCriteria[0].Semester;
                classes_Period = classesCriteria[0].Period;
                classes_Section = classesCriteria[0].Section;
                classes_Block = classesCriteria[0].Block;
            }

            //
            //  Reference Schools criteria node and extract the selected values.
            //
            var schools_SchoolType = "";
            var schools_School = "";
            //var schools_SchoolID = "";
            var schoolsCriteria = criteriaController.ParseCriteria<E3Criteria.Associations.Schools.ValueObject>("Schools");
            if (schoolsCriteria.Count > 0)
            {
                schools_SchoolType = schoolsCriteria[0].SchoolType;
                schools_School = schoolsCriteria[0].School;
                //schools_SchoolID = schoolsCriteria[0].SchoolId;
            }

			//
			// Decide what columns to show.  To do this we must consider the UserRole (two choices at this time), the 
            // Assessment Category (three choices at this time) and the schedule Level (four possibilities at this 
            // time), however, after mapping out all the possible combinations (24 of them), its very sparse per the 
            // switch construct below.  Although switching on assessment category is unnecessary, I have left it in
            // to help with the thinking process should this logic ever need changing.
			var colDistrict = radGridResults.Columns[2];
			var colSchool = radGridResults.Columns[3];
			var colClass = radGridResults.Columns[4];
			var colTeacher = radGridResults.Columns[5];

			colDistrict.Visible = false;
			colSchool.Visible = false;
			colClass.Visible = false;
			colTeacher.Visible = false;

			switch (UserRole)
			{
				case "State":
                    colDistrict.Visible = true;

					//TODO: Schedule Level Dropdown should be a key/value pair instead of a one-column array list of string, 
					//      because when user selects:  
					//      "Assessment" or "District" then we should pass"Assessment" to the SP, 
					//      "School" then we should pass"District" to the SP, 
					//      "Class" then we should pass "School" to the SP.
					//
					//      For now, I am just going to use a switch to make this happen.  If the underlying SP should ever
					//      be re-written, then we can remove this goofy translation.
					switch (scheduleCriteria[0].ScheduleLevel)
					{
						case "Assessment":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.State;
							break;

						case "District":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.ClientID;
							break;
					}
					break;

				case "District":
					//TODO: Schedule Level Dropdown should be a key/value pair instead of a one-column array list of string, 
                    //      because when user selects:  
                    //      "Assessment" or "District" then we should pass"Assessment" to the SP, 
                    //      "School" then we should pass"District" to the SP, 
                    //      "Class" then we should pass "School" to the SP.
                    //
                    //      For now, I am just going to use a switch to make this happen.  If the underlying SP should ever
                    //      be re-written, then we can remove this goofy translation.
                    switch (scheduleCriteria[0].ScheduleLevel)
                    {
						case "State":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.State;
							break;

						case "ClientID":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.ClientID;
							break;

						case "Assessment":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.District;
                            break;

                        case "School":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.School;
                            break;

                        case "Class":
							scheduleCriteria_ScheduleLevel = AssessmentScheduleLevels.Class;
                            break;
                    }

					switch (scheduleCriteria_Category)
			        {
				        case "State":
				        case "District":
                        case "Classroom":
                            switch (scheduleCriteria_ScheduleLevel)
			                {
								case AssessmentScheduleLevels.School:
                                    colSchool.Visible = true;
                                    break;

								case AssessmentScheduleLevels.Class:
                                    colSchool.Visible = true;
                                    colClass.Visible = true;
                                    colTeacher.Visible = true;
                                    break;
                            }
					        break;
                    }

                    break;
			}

            //
            // Now make the call to the business object get our resulting dataset.
            //

            //if (Status_Status == string.Empty /*|| IncludeUnproofedAssessments*/)
            //    Status_Status = "All";            
            bool HasSecurePermission = false;
            if (UserHasPermission(Permission.Access_SecureTesting))
            {
                HasSecurePermission = true;
            }
            

            var searchResults = AssessmentSchedule.SearchAssessmentSchedules(gi: SessionObject.GlobalInputs,
																					ScheduleLevel: scheduleCriteria_ScheduleLevel,
                                                                                     //CurrGrade:curriculum_Grade,
                                                                                     ClassGrade: curriculum_Grade,
                                                                                     //CurrSubject: curriculum_Subject,
                                                                                     ClassSubject: curriculum_Subject,                                                                                     
                                                                                     //CurrCourse: curriculum_Curriculum,
                                                                                     ClassCourse: curriculum_Curriculum,
                                                                                     Teacher: classes_Teacher,
                                                                                     Section: classes_Section,
                                                                                     Period: classes_Period,
                                                                                     Block: classes_Block,
                                                                                     Semester: classes_Semester,
                                                                                     School:schools_School,
                                                                                     SchoolType: schools_SchoolType,
                                                                                     TestType: curriculum_Type,
                                                                                     Term: curriculum_Term,
                                                                                     UserPage: SessionObject.LoggedInUser.Page, 
                                                                                     Year: districtParms.Year,
                                                                                     Curriculum: "",//curriculum_ID.ToString(),
                                                                                     TestCategory: scheduleCriteria_Category,
                                                                                     DistrictID: districts2_District,
                                                                                     Proofed: Status_Status,
                                                                                     HasSecurePermission: HasSecurePermission);
                                                                                     


			//TODO: Lacking sufficient time to properly code what the SP returns as ScheduleInstance data, I have commented this section out and will alternately populate this object within the Caller's logic.
			//switch (scheduleCriteria_ScheduleLevel)
			//{
			//	case ScheduleLevels.District:
			//		foreach (var aSched in searchResults) { AssessScheduleKeys.Add(aSched.TestID, aSched.TestID); Debug.WriteLine(aSched.TestID.ToString() + " ^ " + aSched.TestID.ToString()); }
			//		break;

			//	case ScheduleLevels.School:
			//		foreach (var aSched in searchResults) AssessScheduleKeys.Add(aSched.TestID, aSched.SchoolID);
			//		break;

			//	case ScheduleLevels.Class:
			//		foreach (var aSched in searchResults) AssessScheduleKeys.Add(aSched.TestID, aSched.ClassID);
			//		break;
			//}


			//TODO: Lacking sufficient time to properly code what the SP returns as ScheduleInstance data, I am populating the ScheduleInstances object directly from here.
			//
			DataTableCount = searchResults.Count.ToString();
			var targetSchedLevel = ScheduleLevelsList.Find(x => x.ID == (int)scheduleCriteria_ScheduleLevel);

			var parentSchedLevel = (scheduleCriteria_ScheduleLevel == AssessmentScheduleLevels.District) ? 
									targetSchedLevel :
									ScheduleLevelsList.Find(x => x.ID == Math.Max((int)scheduleCriteria_ScheduleLevel - 1, 1));

			var adminSchedType = ScheduleTypesList.Find(x => x.TypeName == "Admin");
			var contentSchedType = ScheduleTypesList.Find(x => x.TypeName == "Content");
			var printSchedType = ScheduleTypesList.Find(x => x.TypeName == "Print");

			var serializer = new JavaScriptSerializer();
			var SchedKeysList = new List<string>();

			SchedulesList = new List<Scheduling.Schedule>();
			Scheduling.Schedule sched;
			string[] arryParsedID;
			foreach (var assessSched in searchResults)
			{

				arryParsedID = assessSched.ID.Split('_');

				SchedKeysList.Add(arryParsedID[0] + "|" + arryParsedID[2]);

				sched = new Scheduling.Schedule()
				{

					ScheduleTypeID = adminSchedType.TypeID,
					ScheduleTypeName = adminSchedType.TypeName,
					CssStyle = adminSchedType.DisplayStyle,
					DocumentTypeID = adminSchedType.DocTypeID,
					IsStartable = adminSchedType.IsStartable,
					IsEndable = adminSchedType.IsEndable,
					IsLockable = adminSchedType.IsLockable, 
					DisplayOrder = adminSchedType.DisplayOrder,
					schedID = DataIntegrity.ConvertToInt(arryParsedID[0]),  //TODO: When you get back to using schedule tables, this will point to ID in ScheduleInstances table.
					schedLvlID = (int)scheduleCriteria_ScheduleLevel,
					schedLvlEntityID = DataIntegrity.ConvertToInt(arryParsedID[2]),
					LevelLabel = targetSchedLevel.Name, 
					ParentLevelLabel = string.IsNullOrEmpty(parentSchedLevel.Name) ? "" : parentSchedLevel.Name,
					Locked = assessSched.AdminLock,
					Lock_Inherited = DataIntegrity.ConvertToBool(assessSched.AdminLock_Inherited),
					Lock_Begin = assessSched.AdminLock_Begin,
					Lock_End = assessSched.AdminLock_End, 
					Lock_Min = assessSched.AdminLock_Min, 
					Lock_Max = assessSched.AdminLock_Max,
					Lock_EffectiveBegin = assessSched.AdminLock_EffectiveBegin,
					Lock_EffectiveEnd = assessSched.AdminLock_EffectiveEnd,
					Lock_Inactive = adminSchedType.UnlockLabel,
					Lock_Active = adminSchedType.LockLabel, 
					Lock_Label = "Admin" //assessSched.AdminLock_Label
				};
				SchedulesList.Add(sched);
				if (scheduleCriteria_ScheduleLevel == AssessmentScheduleLevels.District || scheduleCriteria_ScheduleLevel == AssessmentScheduleLevels.School)
				{
					sched = new Scheduling.Schedule()
					{
						ScheduleTypeID = contentSchedType.TypeID,
						ScheduleTypeName = contentSchedType.TypeName,
						CssStyle = contentSchedType.DisplayStyle,
						DocumentTypeID = contentSchedType.DocTypeID,
						IsStartable = contentSchedType.IsStartable,
						IsEndable = contentSchedType.IsEndable,
						IsLockable = contentSchedType.IsLockable,
						DisplayOrder = adminSchedType.DisplayOrder,
						schedID = DataIntegrity.ConvertToInt(arryParsedID[0]),  //TODO: When you get back to using schedule tables, this will point to ID in ScheduleInstances table.
						schedLvlID = (int)scheduleCriteria_ScheduleLevel,
						schedLvlEntityID = DataIntegrity.ConvertToInt(arryParsedID[2]),
						LevelLabel = targetSchedLevel.Name,
						ParentLevelLabel = parentSchedLevel.Name,
						Locked = assessSched.ContentLock,
						Lock_Begin = assessSched.ContentLock_Begin,
						Lock_End = assessSched.ContentLock_End,
						Lock_Inherited = DataIntegrity.ConvertToBool(assessSched.ContentLock_Inherited),
						Lock_Min = assessSched.ContentLock_Min,
						Lock_Max = assessSched.ContentLock_Max,
						Lock_EffectiveBegin = assessSched.ContentLock_EffectiveBegin,
						Lock_EffectiveEnd = assessSched.ContentLock_EffectiveEnd,
						Lock_Inactive = contentSchedType.UnlockLabel,
						Lock_Active = contentSchedType.LockLabel,
						Lock_Label = assessSched.ContentLock_Label
					};
					SchedulesList.Add(sched);

					if (scheduleCriteria_ScheduleLevel == AssessmentScheduleLevels.District)
					{
						sched = new Scheduling.Schedule()
						{
							ScheduleTypeID = printSchedType.TypeID,
							ScheduleTypeName = printSchedType.TypeName,
							CssStyle = printSchedType.DisplayStyle,
							DocumentTypeID = printSchedType.DocTypeID,
							IsStartable = printSchedType.IsStartable,
							IsEndable = printSchedType.IsEndable,
							IsLockable = printSchedType.IsLockable,
							DisplayOrder = printSchedType.DisplayOrder,
							schedID = DataIntegrity.ConvertToInt(arryParsedID[0]),  //TODO: When you get back to using schedule tables, this will point to ID in ScheduleInstances table.
							schedLvlID = (int)scheduleCriteria_ScheduleLevel,
							schedLvlEntityID = DataIntegrity.ConvertToInt(arryParsedID[2]),
							LevelLabel = targetSchedLevel.Name,
							ParentLevelLabel = parentSchedLevel.Name,
							Locked = assessSched.PrintLock,
							Lock_Begin = assessSched.PrintLock_Begin,
							Lock_End = assessSched.PrintLock_End,
							Lock_Inherited = DataIntegrity.ConvertToBool(assessSched.PrintLock_Inherited),
							Lock_Min = assessSched.PrintLock_Min,
							Lock_Max = assessSched.PrintLock_Max,
							Lock_EffectiveBegin = assessSched.PrintLock_EffectiveBegin,
							Lock_EffectiveEnd = assessSched.PrintLock_EffectiveEnd,
							Lock_Inactive = printSchedType.UnlockLabel,
							Lock_Active = printSchedType.LockLabel,
							Lock_Label = assessSched.PrintLock_Label
						};
						SchedulesList.Add(sched);
					}
				}

			}

            radGridResults.DataSource = searchResults;

            radGridResults.DataBind();
			
			//Stash key data from SchedulesList in viewstate because we don't want to query for them again.
			if (ViewState["SchedKeys"] == null) ViewState.Add("SchedKeys", "");
			ViewState["SchedKeys"] = serializer.Serialize(SchedKeysList);

			if (ViewState["SchedLevelForSave"] == null) ViewState.Add("SchedLevelForSave",0);
			SchedLevelForSave = scheduleCriteria_ScheduleLevel;
			ViewState["SchedLevelForSave"] = (int)SchedLevelForSave;
        }